feat: adding a crossword puzzle generator to the game
This commit is contained in:
parent
f9556804d7
commit
9ba6ae33d3
22
Cargo.toml
Normal file
22
Cargo.toml
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
[package]
|
||||||
|
name = "regexle"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
csv = "1.3.0"
|
||||||
|
fancy-regex = "0.13.0"
|
||||||
|
rayon = "1.10.0"
|
||||||
|
serde = "1.0.209"
|
||||||
|
serde_derive = "1.0.209"
|
||||||
|
wasm_crossword_generator = "0.0.4"
|
||||||
|
rand = "0.8.5"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "checker"
|
||||||
|
path = "src/checker/bin/main.rs"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "generator"
|
||||||
|
path = "src/generator/bin/main.rs"
|
||||||
|
|
@ -1,11 +0,0 @@
|
|||||||
[package]
|
|
||||||
name = "regex-checker"
|
|
||||||
version = "0.1.0"
|
|
||||||
edition = "2021"
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
csv = "1.3.0"
|
|
||||||
fancy-regex = "0.13.0"
|
|
||||||
rayon = "1.10.0"
|
|
||||||
serde = "1.0.209"
|
|
||||||
serde_derive = "1.0.209"
|
|
@ -3,11 +3,8 @@ use std::error::Error;
|
|||||||
use fancy_regex::Regex;
|
use fancy_regex::Regex;
|
||||||
use rayon::iter::{IntoParallelIterator, IntoParallelRefIterator};
|
use rayon::iter::{IntoParallelIterator, IntoParallelRefIterator};
|
||||||
use rayon::iter::ParallelIterator;
|
use rayon::iter::ParallelIterator;
|
||||||
use crate::utils::{read_csv, read_lines, write_to_csv};
|
use regexle::utils::{read_csv, read_lines, write_to_csv};
|
||||||
use crate::word::{Answer, Word};
|
use regexle::word::{Answer, Word};
|
||||||
|
|
||||||
mod word;
|
|
||||||
mod utils;
|
|
||||||
|
|
||||||
|
|
||||||
fn map_to_answers(regex: String, words: &Vec<Word>) -> Vec<Answer> {
|
fn map_to_answers(regex: String, words: &Vec<Word>) -> Vec<Answer> {
|
||||||
@ -41,7 +38,7 @@ fn main() -> Result<(), Box<dyn Error>> {
|
|||||||
let regexes = read_lines(regex_chart)?;
|
let regexes = read_lines(regex_chart)?;
|
||||||
|
|
||||||
let word_freq_chart = "./word_freq.csv";
|
let word_freq_chart = "./word_freq.csv";
|
||||||
let mut words = read_csv(word_freq_chart)?;
|
let mut words: Vec<Word> = read_csv(word_freq_chart)?;
|
||||||
words.truncate(10000);
|
words.truncate(10000);
|
||||||
let processed_words: Vec<Word> = words.into_par_iter().filter(|word| word.word.len() > 2).collect();
|
let processed_words: Vec<Word> = words.into_par_iter().filter(|word| word.word.len() > 2).collect();
|
||||||
|
|
51
src/generator/bin/main.rs
Normal file
51
src/generator/bin/main.rs
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
use std::error::Error;
|
||||||
|
use rayon::iter::{IntoParallelRefIterator, ParallelIterator};
|
||||||
|
use wasm_crossword_generator::*;
|
||||||
|
use regexle::utils::read_csv;
|
||||||
|
use regexle::word::Answer;
|
||||||
|
|
||||||
|
|
||||||
|
fn print_puzzle(puzz: PerWordPuzzle) {
|
||||||
|
for word in puzz.puzzle.solution.words.iter() {
|
||||||
|
println!("{:?}", word);
|
||||||
|
}
|
||||||
|
puzz.puzzle.grid.iter().for_each(|row| {
|
||||||
|
row.row.iter().for_each(|cell|
|
||||||
|
print!("{:?}", cell)
|
||||||
|
);
|
||||||
|
println!();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
fn main() -> Result<(), Box<dyn Error>> {
|
||||||
|
let records: Vec<Answer> = read_csv("processed_answers.csv")?;
|
||||||
|
|
||||||
|
let words: Vec<Word> = records.par_iter().map(|ans| Word { text: ans.answer.clone(), clue: Option::from(ans.question.clone()) }).collect();
|
||||||
|
// A real SolutionConf would probably want "requirements" to allow for retrying crossword
|
||||||
|
// generation. Because there is only one word, we know we'll get the world's simplest puzzle in
|
||||||
|
// one try.
|
||||||
|
let solution_conf = SolutionConf {
|
||||||
|
words,
|
||||||
|
max_words: 20,
|
||||||
|
width: 10,
|
||||||
|
height: 10,
|
||||||
|
requirements: None,
|
||||||
|
initial_placement: None,
|
||||||
|
};
|
||||||
|
|
||||||
|
// A PerWordPuzzle is one where the player only guesses words, not locations. The player is
|
||||||
|
// immediately informed if the guess is correct or not.
|
||||||
|
let mut puzzle = PerWordPuzzle::new(solution_conf)?;
|
||||||
|
// println!("{:?}", puzzle.puzzle.grid);
|
||||||
|
print_puzzle(puzzle);
|
||||||
|
// let guess = PlacedWord {
|
||||||
|
// // Because it is a PerWordPuzzle, the placement is ignored, unlike other Playmodes.
|
||||||
|
// placement: Placement { x: 0, y: 0, direction: rand::random() },
|
||||||
|
// // NOTE: you don't need to match the "clue" field, it is ignored for purposes of PartialEq
|
||||||
|
// word: Word { text: "library".to_string(), clue: None },
|
||||||
|
// };
|
||||||
|
// let guess_result = puzzle.guess_word(guess)?;
|
||||||
|
//
|
||||||
|
// // Because there is only one word, the guess will result in "Complete" instead of "Correct"
|
||||||
|
// assert_eq!(guess_result, GuessResult::Complete);
|
||||||
|
Ok(())
|
||||||
|
}
|
3
src/lib.rs
Normal file
3
src/lib.rs
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
|
||||||
|
pub mod utils;
|
||||||
|
pub mod word;
|
@ -3,15 +3,19 @@ use std::fs::File;
|
|||||||
use std::io::{self, BufRead};
|
use std::io::{self, BufRead};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use csv::{QuoteStyle, ReaderBuilder, WriterBuilder};
|
use csv::{QuoteStyle, ReaderBuilder, WriterBuilder};
|
||||||
use crate::word::{Answer, Word};
|
use serde::de::DeserializeOwned;
|
||||||
|
use serde::{Serialize};
|
||||||
|
|
||||||
pub fn read_csv(file_path: &str) -> Result<Vec<Word>, Box<dyn Error>> {
|
pub fn read_csv<T>(file_path: &str) -> Result<Vec<T>, Box<dyn Error>>
|
||||||
|
where
|
||||||
|
T: DeserializeOwned,
|
||||||
|
{
|
||||||
let file = File::open(file_path)?;
|
let file = File::open(file_path)?;
|
||||||
let mut rdr = ReaderBuilder::new().has_headers(true).from_reader(file);
|
let mut rdr = ReaderBuilder::new().has_headers(true).from_reader(file);
|
||||||
let mut records = Vec::new();
|
let mut records = Vec::new();
|
||||||
|
|
||||||
for result in rdr.deserialize() {
|
for result in rdr.deserialize() {
|
||||||
let record: Word = result?;
|
let record= result?;
|
||||||
records.push(record);
|
records.push(record);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -19,7 +23,9 @@ pub fn read_csv(file_path: &str) -> Result<Vec<Word>, Box<dyn Error>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn write_to_csv(records: Vec<Answer>, path: &str) -> Result<(), Box<dyn Error>> {
|
pub fn write_to_csv<T>(records: Vec<T>, path: &str) -> Result<(), Box<dyn Error>>
|
||||||
|
where
|
||||||
|
T: Serialize,{
|
||||||
// Create a new CSV writer with the file path
|
// Create a new CSV writer with the file path
|
||||||
let file = File::create(path)?;
|
let file = File::create(path)?;
|
||||||
let mut wtr = WriterBuilder::new()
|
let mut wtr = WriterBuilder::new()
|
@ -2,13 +2,13 @@ use serde_derive::{Deserialize, Serialize};
|
|||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
pub struct Word {
|
pub struct Word {
|
||||||
pub(crate) word: String,
|
pub word: String,
|
||||||
pub(crate) count: i64,
|
pub count: i64,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
pub struct Answer {
|
pub struct Answer {
|
||||||
pub(crate) question: String,
|
pub question: String,
|
||||||
pub(crate) answer: String,
|
pub answer: String,
|
||||||
pub(crate) count: i64,
|
pub count: i64,
|
||||||
}
|
}
|
Can't render this file because it is too large.
|
Loading…
x
Reference in New Issue
Block a user