Skip to content

Commit

Permalink
scoring
Browse files Browse the repository at this point in the history
  • Loading branch information
jayshrivastava committed Apr 15, 2024
1 parent 78b0bfe commit 4b80c1a
Show file tree
Hide file tree
Showing 8 changed files with 7,788 additions and 20 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ leptos = { version = "0.6.9", features = ["csr", "nightly"] }
stylance = "0.3.0"
rand = "0.9.0-alpha.1"
chrono = "0.4.37"
lazy_static = "1.4.0"

[package.metadata.stylance]

Expand Down
10 changes: 10 additions & 0 deletions src/letter_gen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@ impl Generator for LetterGenerator {
fn next_n_letters(&mut self, n: usize) -> Vec<char>{
return self.chars[self.seq..std::cmp::min(self.seq + n, self.chars.len())].to_vec()
}

fn calc_score(&self, calc_score: fn(&Vec<&str>) -> u32) -> u32 {
return calc_score(&self.words)
}
}


Expand Down Expand Up @@ -103,10 +107,16 @@ impl Generator for TestGenerator {
let substring = &TEST_LETTERS[self.idx..std::cmp::min(self.idx + n, TEST_LETTERS.len())];
substring.chars().collect()
}

fn calc_score(&self, calc_score: fn(&Vec<&str>) -> u32) -> u32 {
return calc_score(&vec![TEST_LETTERS])
}
}

pub trait Generator {
fn next_letter(&mut self) -> Option<char>;

fn next_n_letters(&mut self, n: usize) -> Vec<char>;

fn calc_score(&self, calc_score: fn(&Vec<&str>) -> u32) -> u32;
}
84 changes: 71 additions & 13 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,28 @@ use rand::{random, Rng};
mod header;
mod trie;
mod words;
mod scoring;

use leptos::*;
use stylance::import_crate_style;
use leptos::logging::log;
use core::time::Duration;
use crate::letter_gen::{Generator, LetterGenerator, TestGenerator, MIN_WORD_SIZE};
use crate::scoring::get_score_single;
use crate::trie::TrieNode;
use crate::words::WORDS;

import_crate_style!(styles, "./src/styles.module.scss");

// NB: The width variable exists separately in scss as well.
const GRID_WIDTH: usize = 9;
const GRID_HEIGHT: usize = 11;
const GRID_HEIGHT: usize = 9;
const GRID_SIZE: usize =GRID_WIDTH * GRID_HEIGHT;

const LOOKAHEAD: usize = 3;

const LAST_WORDS_WINDOW: usize= 3;

const EMPTY: char = ' ';

const TICK: u64 = 1;
Expand Down Expand Up @@ -74,22 +78,38 @@ fn make_trie() -> TrieNode {
t
}

#[derive(Clone)]
struct WordWithKey {
word: &'static str,
key: u64,
}

fn make_word_with_key(word: &'static str) -> WordWithKey {
return WordWithKey{
word,
key: random(),
}
}

#[component]
fn App() -> impl IntoView {
let (gen, set_gen) = create_signal(TestGenerator::new());
let (grid, set_grid) = create_signal(make_block_vec(set_gen));
let (current, set_current) = create_signal(GRID_WIDTH / 2);
let (checking, set_checking) = create_signal(false);
let (t, _) = create_signal(make_trie());
let (next_letters, set_next_letters) = create_signal(vec![]);
let (game_meta_text, set_game_meta_text) = create_signal(vec![]);
let (score, set_score) = create_signal(0);
let (last_words, set_last_words) = create_signal(vec![]);

// Set next letters.
create_effect(move |_| {
set_gen.update(|g| {
set_next_letters.update(|nl| *nl = g.next_n_letters(LOOKAHEAD))
set_game_meta_text.update(|nl| *nl = g.next_n_letters(LOOKAHEAD))
});
});

let spawn = move || {
let spawn = move || {
if grid.get()[GRID_WIDTH/2].val.get() != EMPTY {
// TODO: handle user lost the game condition
panic!("TODO: lost")
Expand All @@ -103,7 +123,7 @@ fn App() -> impl IntoView {
panic!("TODO: you won")
}
*val = next.unwrap();
set_next_letters.update(|nl| *nl = g.next_n_letters(LOOKAHEAD));
set_game_meta_text.update(|nl| *nl = g.next_n_letters(LOOKAHEAD));
})
});
});
Expand Down Expand Up @@ -177,10 +197,11 @@ fn App() -> impl IntoView {
}
match dir {
0 => {
j -= GRID_WIDTH;
if j < 0 {

if j-GRID_WIDTH < 0 {
break
}
j -= GRID_WIDTH;
},
1 => {
if (j+1) % GRID_WIDTH < j % GRID_WIDTH {
Expand All @@ -207,6 +228,8 @@ fn App() -> impl IntoView {
}
}
log!("{:?}", words);

let found_words = words.len() > 0;
let idx_final_iter = &indexes_final;
for word_idx_arr in idx_final_iter {
for idx in word_idx_arr {
Expand All @@ -218,7 +241,13 @@ fn App() -> impl IntoView {
}
}
let idx_final_clone = indexes_final.clone();
let words_clone = words.clone();
if !found_words {
set_checking(false);
return
}
set_timeout(move || {
// Update grid. TODO: slide letters down.
for word_idx_arr in idx_final_clone {
for idx in word_idx_arr {
grid.with(|blocks: &Vec<BlockState>| {
Expand All @@ -227,13 +256,25 @@ fn App() -> impl IntoView {
});
}
}
}, Duration::from_millis(500));

// Set last words.
for word in words_clone {
set_last_words.update(|last_words| {
last_words.insert(0, make_word_with_key(word));
if last_words.len() > LAST_WORDS_WINDOW {
last_words.pop();
}
});
set_score.update(|score| {
*score = *score + get_score_single(word)
});
}

set_checking(false);
}, Duration::from_millis(500));
});
});

set_checking(false);

};

let handle_key_press = move |code: &str| {
Expand Down Expand Up @@ -287,9 +328,6 @@ fn App() -> impl IntoView {
</div>
</For>
</div>
<div>
<p class=styles::next_letters>"Up Next: "{move || next_letters.get().iter().map(|&c| c.to_string()).collect::<Vec<_>>().join(", ")}</p>
</div>
<div class=styles::arrow_container>
<button class=styles::arrow_button
on:mouseup=move |_| { handle_key_press(KEY_A); }
Expand All @@ -308,6 +346,26 @@ fn App() -> impl IntoView {
on:touchend=move |ev| {ev.prevent_default(); handle_key_press(KEY_D); }
> "➡️"</button>
</div>
<div>
<p class=styles::game_meta_text>"Up Next: "{move || game_meta_text.get().iter().map(|&c| c.to_string())
.collect::<Vec<_>>().join(", ")}</p>
</div>
<div>
<p class=styles::game_meta_text>"Score: "{move || score.get()}</p>
</div>
<div>
<p class=styles::game_meta_text>{"Previous Words:"}</p>
<div class=styles::last_words_indent>
<For
each=last_words
key=|word_with_key| word_with_key.key.clone()
let: wwk
>
<p class=styles::game_meta_text>{format!("{} - {}", wwk.word, get_score_single(wwk.word))}</p>
</For>
</div>
</div>

</div>
}
}
Expand Down
43 changes: 43 additions & 0 deletions src/scoring.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
use std::collections::HashMap;
use lazy_static::lazy_static;

lazy_static! {
static ref SCRABBLE_POINTS: HashMap<char, u32> = {
let mut map = HashMap::new();
map.insert('A', 1);
map.insert('E', 1);
map.insert('I', 1);
map.insert('O', 1);
map.insert('U', 1);
map.insert('L', 1);
map.insert('N', 1);
map.insert('S', 1);
map.insert('T', 1);
map.insert('R', 1);
map.insert('D', 2);
map.insert('G', 2);
map.insert('B', 3);
map.insert('C', 3);
map.insert('M', 3);
map.insert('P', 3);
map.insert('F', 4);
map.insert('H', 4);
map.insert('V', 4);
map.insert('W', 4);
map.insert('Y', 4);
map.insert('K', 5);
map.insert('J', 8);
map.insert('X', 8);
map.insert('Q', 10);
map.insert('Z', 10);
map
};
}

pub fn get_score_single(word: &str) -> u32 {
let mut sc = 0;
for c in word.chars() {
sc += SCRABBLE_POINTS.get(&c).unwrap()
}
return sc
}
11 changes: 8 additions & 3 deletions src/styles.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@ body {

// HEADER
.header {
margin: 1% auto;
margin: 4% auto 2%;
width: 15%;
text-align: center;
font-family: Arial, Helvetica, sans-serif;
font-size: 1.5em;
}

// GRID
Expand All @@ -39,11 +40,15 @@ body {
font-family: Arial, Helvetica, sans-serif;
}

// NEXT LETTERS
.next_letters {
// NEXT LETTERS, SCORING, PAST WORDS
.game_meta_text {
font-family: Arial, Helvetica, sans-serif;
}

.last_words_indent {
margin-left: 5%;
}

// ARROWS
.arrow-container {
margin-top: 10px;
Expand Down
7,647 changes: 7,646 additions & 1 deletion src/words.rs

Large diffs are not rendered by default.

11 changes: 8 additions & 3 deletions styles/bundled.scss
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@ body {

// HEADER
.header-94e563a {
margin: 1% auto;
margin: 4% auto 2%;
width: 15%;
text-align: center;
font-family: Arial, Helvetica, sans-serif;
font-size: 1.5em;
}

// GRID
Expand All @@ -39,11 +40,15 @@ body {
font-family: Arial, Helvetica, sans-serif;
}

// NEXT LETTERS
.next_letters-94e563a {
// NEXT LETTERS, SCORING, PAST WORDS
.game_meta_text-94e563a {
font-family: Arial, Helvetica, sans-serif;
}

.last_words_indent-94e563a {
margin-left: 5%;
}

// ARROWS
.arrow-container-94e563a {
margin-top: 10px;
Expand Down

0 comments on commit 4b80c1a

Please sign in to comment.