26 Commits

Author SHA1 Message Date
277d833da2 Add AVX2 Dependency 2023-04-05 22:39:59 +02:00
00e3d6fd0f Fix Cache 2023-04-05 13:07:14 +02:00
fb8f935617 Fix Cache and Bump Version 2023-04-05 13:05:15 +02:00
2a112ac49c Add Output Limit 2023-04-05 02:43:28 +02:00
e7c1fd1ef7 Fixing Something? 2023-04-05 00:33:21 +02:00
80eeaad5d5 Add output for machines 2023-04-04 22:38:02 +02:00
64158cf45b Remove Timer from Progressbar 2023-04-04 21:44:43 +02:00
e4b26755ea Revert "Print Progressbar to stdout"
This reverts commit 5607dcc72c.
2023-04-04 17:34:12 +02:00
5607dcc72c Print Progressbar to stdout 2023-04-04 17:29:04 +02:00
5c9bcfc2ec Add SQL to Makefile 2023-04-04 16:31:48 +02:00
1df33249c4 Add Makefile for easier building 2023-04-04 00:36:40 +02:00
ef2755115c Fix tests 2023-04-01 11:14:44 +02:00
b32aac0aba Fix naming and Tests 2023-04-01 11:08:57 +02:00
a9a3e70aef Update Roadmap 2023-04-01 11:07:12 +02:00
c477a52f92 Slowdown ProgressBar and add Stderr as output 2023-04-01 11:02:49 +02:00
818de6be47 Abstractions 2023-04-01 10:30:25 +02:00
8f15b42146 Add Issue Templates 2023-03-21 18:31:50 +01:00
b8d912881d Fix SQL-Interface 2023-03-19 21:18:40 +01:00
02404792a5 Bump Version 2023-03-19 11:59:39 +01:00
59272ed3e7 Add Complex Output Patterns 2023-03-19 11:57:22 +01:00
322ba65656 Add Caches 2023-03-18 10:27:34 +01:00
b082d6cd8d Fix Imports 2023-03-16 21:33:23 +01:00
f4bcde73f9 Add Roadmap 2023-03-16 21:09:41 +01:00
0e31714582 Add Roadmap 2023-03-16 21:08:56 +01:00
229c858d9a Optimize Workflows 2023-03-16 20:40:37 +01:00
abf6953172 Optimize Workflows 2023-03-16 20:40:17 +01:00
22 changed files with 464 additions and 103 deletions

40
.github/ISSUE_TEMPLATE/bug.yml vendored Normal file
View File

@ -0,0 +1,40 @@
name: Bug Report
description: Create a report to fix a bug
labels: [bug]
title: "[BUG] <title>"
body:
- type: textarea
id: description
attributes:
label: Description
description: A clear and concise description of what the bug is.
validations:
required: true
- type: textarea
id: reproduction
attributes:
label: Reproduction
description: Steps to reproduce the behavior.
validations:
required: true
- type: textarea
id: expected-behavior
attributes:
label: Expected Behavior
description: A clear and concise description of what you expected to happen.
validations:
required: true
- type: textarea
id: actual-behavior
attributes:
label: Actual Behavior
description: A clear and concise description of what actually happened.
validations:
required: true
- type: textarea
id: additional-context
attributes:
label: Additional Context
description: Add any other context about the problem here.
validations:
required: false

35
.github/ISSUE_TEMPLATE/feature.yml vendored Normal file
View File

@ -0,0 +1,35 @@
name: Feature Request
description: Suggest an idea for this project
title: "[FEATURE] <title>"
labels: [enhancement]
body:
- type: textarea
id: description
attributes:
label: Description
description: A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
validations:
required: true
- type: textarea
id: solution
attributes:
label: Proposed Solution
description: A clear and concise description of what you want to happen.
validations:
required: true
- type: textarea
id: alternatives
attributes:
label: Alternatives
description: A clear and concise description of any alternative solutions or features you've considered.
validations:
required: false
- type: textarea
id: additional-context
attributes:
label: Additional Context
description: Add any other context or screenshots about the feature request here.
validations:
required: false

View File

@ -16,18 +16,41 @@ jobs:
steps:
- uses: actions/checkout@v3
- name: Cache Cargo modules
id: cache-cargo
uses: actions/cache@v3
continue-on-error: false
with:
path: |
~/.cargo/registry
~/.cargo/git
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-
- name: Build
run: cargo build --verbose
run: make debug
- name: Run tests
run: cargo test --verbose
build-realease:
run: cargo test --verbose -p schemsearch-lib
build-release:
needs:
- build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Cache Cargo modules
id: cache-cargo
uses: actions/cache@v3
continue-on-error: false
with:
path: |
~/.cargo/registry
~/.cargo/git
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-
- name: Build
run: cargo build --verbose --release
run: make
- name: Upload a Build Artifact
uses: actions/upload-artifact@v3.1.2
with:

View File

@ -19,8 +19,19 @@ jobs:
steps:
- uses: actions/checkout@v3
- name: Cache Cargo modules
id: cache-cargo
uses: actions/cache@v3
continue-on-error: false
with:
path: |
~/.cargo/registry
~/.cargo/git
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-
- name: Build
run: cargo build --verbose --release
run: make
- name: Create Tarball
if: ${{ matrix.os != 'windows-latest' }}
run: tar -czvf schemsearch-cli-${{ matrix.os }}.tar.gz -C target/release schemsearch-cli

View File

@ -2,7 +2,7 @@
members = [
"schemsearch-cli",
"schemsearch-lib",
"schemsearch_faster",
"schemsearch-faster",
"schemsearch-files",
"schemsearch-sql",
"schemsearch-java"

28
Makefile Normal file
View File

@ -0,0 +1,28 @@
default:
@echo "Building (Release)...";
cargo rustc --release --color=always -p schemsearch-cli -- -C target-feature=+avx2
sql:
@echo "Building (Release)...";
cargo rustc --release --color=always -p schemsearch-cli --features sql -- -C target-feature=+avx2
debug:
@echo "Building (Debug)...";
cargo build -p schemsearch-cli
install: default
@echo "Installing...";
install -Dm755 target/release/schemsearch-cli /usr/bin/schemsearch
uninstall:
@echo "Uninstalling...";
rm -f /usr/bin/schemsearch
java:
@echo "Building Java...";
@echo "WARNING: This is WORK IN PROGRESS!";
javac SchemSearch.java
clean:
@echo "Cleaning...";
cargo clean

View File

@ -5,10 +5,10 @@
## WARNING: This is a work in progress and is really simple right now. It will be improved in the future.
| Feature | Status |
|------------------------|--------|
|---------------------------|--------|
| Block search | ✅ |
| Block data less search | ✅ |
| Tile entities search | ❌ |
| Tile entities data search | ❌ |
| Entities search | ❌ |
---
@ -40,6 +40,17 @@ schemsearch-cli --help
---
## Roadmap
A list of features that are planned to be implemented in the future. In order of priority.
- [ ] Full JSON output (Progressbar)
- [ ] Use AVX2 for faster search
- [ ] Tile entities data search
- [ ] Entities search
- [ ] McEdit Schematic support
---
## Building
This project is build using Rust for the CLI and library. It can be built using Cargo.
```bash

View File

@ -1,6 +1,6 @@
[package]
name = "schemsearch-cli"
version = "0.1.0"
version = "0.1.2"
edition = "2021"
license = "AGPL-3.0-or-later"
@ -16,6 +16,8 @@ futures = { version = "0.3", optional = true }
sqlx = { version = "0.6", features = [ "runtime-async-std-native-tls" , "mysql" ], optional = true }
rayon = "1.7.0"
indicatif = { version = "0.17.3", features = ["rayon"] }
serde = "1.0.157"
serde_json = "1.0.94"
[features]
sql = ["dep:schemsearch-sql", "dep:futures", "dep:sqlx"]

View File

@ -0,0 +1,29 @@
use serde::{Deserialize, Serialize};
use schemsearch_lib::{Match, SearchBehavior};
#[derive(Serialize, Deserialize, Debug)]
#[serde(tag = "event")]
pub enum JsonEvent {
Found(FoundEvent),
Init(InitEvent),
End(EndEvent),
}
#[derive(Serialize, Deserialize, Debug)]
pub struct FoundEvent {
pub name: String,
#[serde(flatten, rename = "match")]
pub match_: Match,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct InitEvent {
pub total: u32,
pub search_behavior: SearchBehavior,
pub start_time: u128,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct EndEvent {
pub end_time: u128,
}

View File

@ -16,16 +16,17 @@
*/
mod types;
mod json_output;
mod sinks;
mod stderr;
use std::fmt::Debug;
use std::fs::File;
use std::io;
use std::io::{BufWriter, Write};
use std::io::Write;
use clap::{command, Arg, ArgAction, ValueHint};
use schemsearch_files::Schematic;
use std::path::PathBuf;
use std::str::FromStr;
use clap::error::ErrorKind;
use schemsearch_lib::{search, SearchBehavior};
use schemsearch_lib::{Match, search, SearchBehavior};
use crate::types::{PathSchematicSupplier, SchematicSupplierType};
#[cfg(feature = "sql")]
use futures::executor::block_on;
@ -37,7 +38,10 @@ use schemsearch_sql::filter::SchematicFilter;
use schemsearch_sql::load_all_schematics;
#[cfg(feature = "sql")]
use crate::types::SqlSchematicSupplier;
use indicatif::{ProgressBar, ParallelProgressIterator, ProgressStyle};
use indicatif::*;
use schemsearch_files::Schematic;
use crate::sinks::{OutputFormat, OutputSink};
use crate::stderr::MaschineStdErr;
fn main() {
#[allow(unused_mut)]
@ -92,20 +96,32 @@ fn main() {
)
.arg(
Arg::new("output")
.help("The output format")
.help("The output format and path [Format:Path] available formats: text, json, csv; available paths: std, err, (file path)")
.short('o')
.long("output")
.action(ArgAction::Append)
.default_value("std")
.value_parser(["std_csv", "file_csv", "std", "file"]),
)
.arg(
Arg::new("output-file")
.help("The output file")
.short('O')
.long("output-file")
.value_hint(ValueHint::FilePath)
.action(ArgAction::Append)
.default_value("text:std")
.value_parser(|s: &str| {
let mut split = s.splitn(2, ':');
let format = match split.next() {
None => return Err("No format specified".to_string()),
Some(x) => x
};
let path = match split.next() {
None => return Err("No path specified".to_string()),
Some(x) => x
};
let format = match OutputFormat::from_str(format) {
Ok(x) => x,
Err(e) => return Err(e.to_string()),
};
let path = match OutputSink::from_str(path) {
Ok(x) => x,
Err(e) => return Err(e.to_string()),
};
Ok((format, path))
}),
)
.arg(
Arg::new("threshold")
@ -125,6 +141,24 @@ fn main() {
.default_value("0")
.value_parser(|s: &str| s.parse::<usize>().map_err(|e| e.to_string())),
)
.arg(
Arg::new("machine")
.help("Output for machines")
.short('m')
.long("machine")
.action(ArgAction::Set)
.default_value("0")
.value_parser(|s: &str| s.parse::<u16>().map_err(|e| e.to_string()))
)
.arg(
Arg::new("limit")
.help("The maximum number of matches to return [0 = Unlimited]")
.short('l')
.long("limit")
.action(ArgAction::Set)
.default_value("50")
.value_parser(|s: &str| s.parse::<usize>().map_err(|e| e.to_string())),
)
.about("Searches for a pattern in a schematic")
.bin_name("schemsearch");
@ -223,52 +257,35 @@ fn main() {
cmd.error(ErrorKind::MissingRequiredArgument, "No schematics specified").exit();
}
let mut output_std = false;
let mut output_std_csv = false;
let mut output_file_csv = false;
let mut output_file = false;
let output: Vec<&(OutputFormat, OutputSink)> = matches.get_many::<(OutputFormat, OutputSink)>("output").expect("Error").collect();
let mut output: Vec<(OutputFormat, Box<dyn Write>)> = output.into_iter().map(|x| (x.0.clone(), x.1.output())).collect();
for x in matches.get_many::<String>("output").expect("Couldn't get output") {
match x.as_str() {
"std" => output_std = true,
"std_csv" => output_std_csv = true,
"file_csv" => output_file_csv = true,
"file" => output_file = true,
_ => {}
for x in &mut output {
write!(x.1, "{}", x.0.start(schematics.len() as u32, &search_behavior, start.elapsed().as_millis())).unwrap();
}
};
let file: Option<File>;
let mut file_out: Option<BufWriter<File>> = None;
if output_file || output_file_csv {
let output_file_path = match matches.get_one::<String>("output-file") {
None => {
cmd.error(ErrorKind::MissingRequiredArgument, "No output file specified").exit();
}
Some(x) => x
};
file = match File::create(output_file_path) {
Ok(x) => Some(x),
Err(e) => {
cmd.error(ErrorKind::Io, format!("Error while creating output file: {}", e.to_string())).exit();
}
};
file_out = Some(BufWriter::new(file.unwrap()));
}
ThreadPoolBuilder::new().num_threads(*matches.get_one::<usize>("threads").expect("Could not get threads")).build_global().unwrap();
let matches: Vec<Result> = schematics.par_iter().progress_with_style(ProgressStyle::with_template("[{elapsed}, ETA: {eta}] {wide_bar} {pos}/{len} {per_sec}").unwrap()).map(|schem| {
let bar = ProgressBar::new(schematics.len() as u64); // "maschine"
bar.set_style(ProgressStyle::with_template("[{elapsed}, ETA: {eta}] {wide_bar} {pos}/{len} {per_sec}").unwrap());
let term_size = *matches.get_one::<u16>("machine").expect("Could not get machine");
if term_size != 0 {
bar.set_draw_target(ProgressDrawTarget::term_like(Box::new(MaschineStdErr { size: term_size })))
}
let max_matching = *matches.get_one::<usize>("limit").expect("Could not get max-matching");
let matches: Vec<SearchResult> = schematics.par_iter().progress_with(bar).map(|schem| {
match schem {
SchematicSupplierType::PATH(schem) => {
let schematic = match load_schem(&schem.path) {
Some(x) => x,
None => return Result {
None => return SearchResult {
name: schem.get_name(),
matches: vec![]
matches: Vec::default()
}
};
Result {
SearchResult {
name: schem.get_name(),
matches: search(schematic, &pattern, search_behavior)
}
@ -277,18 +294,16 @@ fn main() {
SchematicSupplierType::SQL(schem) => {
match schem.get_schematic() {
Ok(schematic) => {
Result {
SearchResult {
name: schem.get_name(),
matches: search(schematic, &pattern, search_behavior)
}
}
Err(e) => {
if !output_std && !output_std_csv {
println!("Error while loading schematic ({}): {}", schem.get_name(), e.to_string());
}
Result {
eprintln!("Error while loading schematic ({}): {}", schem.get_name(), e.to_string());
SearchResult {
name: schem.get_name(),
matches: vec![]
matches: Vec::default()
}
}
}
@ -296,30 +311,27 @@ fn main() {
}
}).collect();
let stdout = io::stdout();
let mut lock = stdout.lock();
let mut matches_count = 0;
for matching in matches {
'outer: for matching in matches {
let schem_name = matching.name;
let matching = matching.matches;
for x in matching {
if output_std {
writeln!(lock, "Found match in '{}' at x: {}, y: {}, z: {}, % = {}", schem_name, x.0, x.1, x.2, x.3).unwrap();
for out in &mut output {
write!(out.1, "{}", out.0.found_match(&schem_name, x)).unwrap();
}
if output_std_csv {
writeln!(lock, "{},{},{},{},{}", schem_name, x.0, x.1, x.2, x.3).unwrap();
}
if output_file {
writeln!(file_out.as_mut().unwrap(), "Found match in '{}' at x: {}, y: {}, z: {}, % = {}", schem_name, x.0, x.1, x.2, x.3).unwrap();
}
if output_file_csv {
writeln!(file_out.as_mut().unwrap(), "{},{},{},{},{}", schem_name, x.0, x.1, x.2, x.3).unwrap();
matches_count += 1;
if max_matching != 0 && matches_count >= max_matching {
break 'outer;
}
}
}
let end = std::time::Instant::now();
println!("Finished in {:.2}s! Searched in {} Schematics", end.duration_since(start).as_secs_f32(), schematics.len());
for x in &mut output {
write!(x.1, "{}", x.0.end(end.duration_since(start).as_millis())).unwrap();
x.1.flush().unwrap();
}
}
fn load_schem(schem_path: &PathBuf) -> Option<Schematic> {
@ -333,8 +345,8 @@ fn load_schem(schem_path: &PathBuf) -> Option<Schematic> {
}
#[derive(Debug, Clone)]
struct Result {
struct SearchResult {
name: String,
matches: Vec<(u16, u16, u16, f32)>,
matches: Vec<Match>,
}

View File

@ -0,0 +1,90 @@
use std::fs::File;
use std::io::BufWriter;
use std::str::FromStr;
use std::io::Write;
use std::time::Duration;
use indicatif::HumanDuration;
use schemsearch_lib::{Match, SearchBehavior};
use crate::json_output::{EndEvent, FoundEvent, InitEvent, JsonEvent};
#[derive(Debug, Clone)]
pub enum OutputSink {
Stdout,
Stderr,
File(String),
}
#[derive(Debug, Clone)]
pub enum OutputFormat {
Text,
CSV,
JSON
}
impl FromStr for OutputFormat {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"text" => Ok(OutputFormat::Text),
"csv" => Ok(OutputFormat::CSV),
"json" => Ok(OutputFormat::JSON),
_ => Err(format!("'{}' is not a valid output format", s))
}
}
}
impl FromStr for OutputSink {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"std" => Ok(OutputSink::Stdout),
"err" => Ok(OutputSink::Stderr),
_ => Ok(OutputSink::File(s.to_string()))
}
}
}
impl OutputSink {
pub fn output(&self) -> Box<dyn Write> {
match self {
OutputSink::Stdout => Box::new(std::io::stdout()),
OutputSink::Stderr => Box::new(std::io::stderr()),
OutputSink::File(path) => Box::new(BufWriter::new(File::create(path).unwrap()))
}
}
}
impl OutputFormat {
pub fn found_match(&self, name: &String, pos: Match) -> String {
match self {
OutputFormat::Text => format!("Found match in '{}' at x: {}, y: {}, z: {}, % = {}\n", name, pos.x, pos.y, pos.z, pos.percent),
OutputFormat::CSV => format!("{},{},{},{},{}\n", name, pos.x, pos.y, pos.z, pos.percent),
OutputFormat::JSON => format!("{}\n", serde_json::to_string(&JsonEvent::Found(FoundEvent {
name: name.clone(),
match_: pos,
})).unwrap())
}
}
pub fn start(&self, total: u32, search_behavior: &SearchBehavior, start_time: u128) -> String {
match self {
OutputFormat::Text => format!("Starting search in {} schematics\n", total),
OutputFormat::CSV => format!("Name,X,Y,Z,Percent\n"),
OutputFormat::JSON => format!("{}\n", serde_json::to_string(&JsonEvent::Init(InitEvent {
total,
search_behavior: search_behavior.clone(),
start_time,
})).unwrap())
}
}
pub fn end(&self, end_time: u128) -> String {
match self {
OutputFormat::Text => format!("Search complete in {}\n", HumanDuration(Duration::from_millis(end_time as u64))),
OutputFormat::CSV => format!("{}\n", end_time),
OutputFormat::JSON => format!("{}\n", serde_json::to_string(&JsonEvent::End(EndEvent{ end_time })).unwrap())
}
}
}

View File

@ -0,0 +1,44 @@
use std::fmt::Debug;
use std::io::Write;
use indicatif::TermLike;
#[derive(Debug)]
pub struct MaschineStdErr { pub(crate) size: u16}
impl TermLike for MaschineStdErr {
fn width(&self) -> u16 {
self.size
}
fn move_cursor_up(&self, _: usize) -> std::io::Result<()> {
Ok(())
}
fn move_cursor_down(&self, _: usize) -> std::io::Result<()> {
Ok(())
}
fn move_cursor_right(&self, _: usize) -> std::io::Result<()> {
Ok(())
}
fn move_cursor_left(&self, _: usize) -> std::io::Result<()> {
Ok(())
}
fn write_line(&self, s: &str) -> std::io::Result<()> {
writeln!(std::io::stderr(), "{}", s)
}
fn write_str(&self, s: &str) -> std::io::Result<()> {
write!(std::io::stderr(), "{}", s)
}
fn clear_line(&self) -> std::io::Result<()> {
Ok(())
}
fn flush(&self) -> std::io::Result<()> {
std::io::stderr().flush()
}
}

View File

@ -18,6 +18,7 @@
use std::path::PathBuf;
#[cfg(feature = "sql")]
use futures::executor::block_on;
#[allow(unused_imports)]
use schemsearch_files::Schematic;
#[cfg(feature = "sql")]
use schemsearch_sql::{load_schemdata, SchematicNode};

View File

@ -1,6 +1,6 @@
[package]
name = "schemsearch_faster"
version = "0.1.0"
version = "0.1.1"
edition = "2021"
license = "AGPL-3.0-or-later"

View File

@ -1,6 +1,6 @@
[package]
name = "schemsearch-files"
version = "0.1.0"
version = "0.1.2"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

View File

@ -1,6 +1,6 @@
[package]
name = "schemsearch-java"
version = "0.1.0"
version = "0.1.1"
edition = "2021"
license = "AGPL-3.0-or-later"

View File

@ -45,8 +45,8 @@ pub extern "system" fn Java_SchemSearch_search<'local>(mut env: JNIEnv<'local>,
});
let mut result = String::new();
for (x, y, z, p) in matches {
result.push_str(&format!("{}, {}, {}, {};", x, y, z, p));
for m in matches {
result.push_str(&format!("{}, {}, {}, {};", m.x, m.y, m.z, m.percent));
}
result.remove(result.len() - 1);
let output = env.new_string(result).expect("Couldn't create java string!");

View File

@ -1,6 +1,6 @@
[package]
name = "schemsearch-lib"
version = "0.1.0"
version = "0.1.2"
edition = "2021"
license = "AGPL-3.0-or-later"
@ -10,3 +10,4 @@ license = "AGPL-3.0-or-later"
hematite-nbt = "0.5.2"
serde = "1.0.152"
schemsearch-files = { path = "../schemsearch-files" }
manual-avx2 = { git = "https://github.com/Chaoscaot/manual-avx2", version = "0.1.0" }

View File

@ -17,11 +17,12 @@
pub mod pattern_mapper;
use serde::{Deserialize, Serialize};
use pattern_mapper::match_palette;
use schemsearch_files::Schematic;
use crate::pattern_mapper::match_palette_adapt;
#[derive(Debug, Clone, Copy)]
#[derive(Debug, Clone, Copy, Deserialize, Serialize)]
pub struct SearchBehavior {
pub ignore_block_data: bool,
pub ignore_block_entities: bool,
@ -35,7 +36,7 @@ pub fn search(
schem: Schematic,
pattern_schem: &Schematic,
search_behavior: SearchBehavior,
) -> Vec<(u16, u16, u16, f32)> {
) -> Vec<Match> {
if schem.width < pattern_schem.width || schem.height < pattern_schem.height || schem.length < pattern_schem.length {
return vec![];
}
@ -46,7 +47,7 @@ pub fn search(
let pattern_schem = match_palette(&schem, &pattern_schem, search_behavior.ignore_block_data);
let mut matches: Vec<(u16, u16, u16, f32)> = Vec::new();
let mut matches: Vec<Match> = Vec::new();
let pattern_data = pattern_schem.block_data.as_slice();
@ -60,7 +61,7 @@ pub fn search(
let air_id = if search_behavior.ignore_air || search_behavior.air_as_any { pattern_schem.palette.get("minecraft:air").unwrap_or(&-1) } else { &-1};
let pattern_blocks = (pattern_schem.width * pattern_schem.height * pattern_schem.length) as f32;
let pattern_blocks = pattern_data.len() as f32;
let pattern_width = pattern_schem.width as usize;
let pattern_height = pattern_schem.height as usize;
@ -87,9 +88,20 @@ pub fn search(
}
}
}
for index in (0..schem_data.len()).step_by(8) {
let pattern_data_slice = schem_data[index..index + 8];
let data = manual_avx2::vec_i::VecInteger::new_i32(&(index..index + 8).map(|i| schem_data[i]).collect::<[i32; 8]>());
}
let matching_percent = matching as f32 / pattern_blocks;
if matching_percent >= search_behavior.threshold {
matches.push((x as u16, y as u16, z as u16, matching_percent));
matches.push(Match {
x: x as u16,
y: y as u16,
z: z as u16,
percent: matching_percent,
});
}
}
}
@ -98,6 +110,25 @@ pub fn search(
return matches;
}
#[derive(Debug, Clone, Copy, Deserialize, Serialize)]
pub struct Match {
pub x: u16,
pub y: u16,
pub z: u16,
pub percent: f32,
}
impl Default for Match {
fn default() -> Self {
Self {
x: 0,
y: 0,
z: 0,
percent: 0.0,
}
}
}
#[inline]
pub fn normalize_data(data: &str, ignore_data: bool) -> &str {
if ignore_data {
@ -195,7 +226,10 @@ mod tests {
println!("{:?}", matches);
assert_eq!(matches.len(), 1);
assert_eq!(matches[0], (1, 0, 3, 1.0));
assert_eq!(matches[0].x, 1);
assert_eq!(matches[0].y, 0);
assert_eq!(matches[0].z, 3);
assert_eq!(matches[0].percent, 1.0);
}
#[test]

View File

@ -1,6 +1,6 @@
[package]
name = "schemsearch-sql"
version = "0.1.0"
version = "0.1.1"
edition = "2021"
license = "AGPL-3.0-or-later"

View File

@ -16,7 +16,7 @@
*/
use std::sync::Mutex;
use sqlx::{ConnectOptions, Executor, MySql, MySqlPool, Pool, Row};
use sqlx::{Executor, MySql, Pool, Row};
use sqlx::mysql::{MySqlConnectOptions, MySqlPoolOptions};
use crate::filter::SchematicFilter;