kripke: add history
This commit is contained in:
4
apps/web/src/lib/global.d.ts
vendored
4
apps/web/src/lib/global.d.ts
vendored
@@ -40,10 +40,6 @@ interface ReadonlyArray<T> {
|
||||
): searchElement is T extends LiteralUnionLike<T> ? T : never;
|
||||
}
|
||||
|
||||
interface Map<K> {
|
||||
has(key: Weaken<K>): key is K;
|
||||
}
|
||||
|
||||
declare module "*&enhanced" {
|
||||
import type { Picture } from "vite-imagetools";
|
||||
|
||||
|
||||
@@ -11,8 +11,8 @@ import Game, { type GameStatus } from "./components/game.svelte";
|
||||
import Rules from "./components/rules.svelte";
|
||||
import Share from "./components/share.svelte";
|
||||
|
||||
import { daily } from "./lib/store";
|
||||
import { getFrameBySeed, getTimeUntilNextGame } from "./lib/system";
|
||||
import { daily } from "./store";
|
||||
|
||||
let { data } = $props();
|
||||
const seed = data.seed;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { type Formula, prettyPrint, tryParse } from "@cannorin/kripke";
|
||||
import { formulaHistory } from "../lib/store";
|
||||
|
||||
let {
|
||||
formula = $bindable<Formula | undefined>(undefined),
|
||||
@@ -11,6 +12,12 @@ let {
|
||||
|
||||
let input = $state(formula ? prettyPrint(formula) : "");
|
||||
let error = $state(false);
|
||||
let history = $derived(
|
||||
[...$formulaHistory]
|
||||
.toSorted(([_a, ac], [_b, bc]) => bc - ac)
|
||||
.slice(0, 10)
|
||||
.map(([a, _ac]) => a),
|
||||
);
|
||||
|
||||
$effect(() => {
|
||||
const fml = tryParse(input);
|
||||
@@ -24,7 +31,16 @@ $effect(() => {
|
||||
});
|
||||
</script>
|
||||
|
||||
{#if history.length > 0}
|
||||
<datalist id="formula">
|
||||
{#each history as fml}
|
||||
<option value={fml}></option>
|
||||
{/each}
|
||||
</datalist>
|
||||
{/if}
|
||||
|
||||
<input
|
||||
id="formula"
|
||||
class={["rounded border border-foreground ring-0 focus:outline-none focus:ring-0 p-2 w-full", error && "border-primary"]}
|
||||
type="text"
|
||||
placeholder="Enter modal formula"
|
||||
|
||||
54
apps/web/src/routes/kripke/lib/multiset.ts
Normal file
54
apps/web/src/routes/kripke/lib/multiset.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
export class MultiSet<T> extends Map<T, number> {
|
||||
constructor(iterable?: Iterable<readonly [T, number]>) {
|
||||
super();
|
||||
if (iterable) {
|
||||
for (const [item, count] of iterable) {
|
||||
this.add(item, count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the specified item to the multiset.
|
||||
* If the item already exists, its count is incremented.
|
||||
*
|
||||
* @param item The element to add.
|
||||
* @param count The number of times to add the element (default is 1).
|
||||
* @returns The current instance for chaining.
|
||||
*/
|
||||
add(item: T, count = 1): this {
|
||||
const currentCount = this.get(item) ?? 0;
|
||||
this.set(item, currentCount + count);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes one or more instances of the specified item.
|
||||
*
|
||||
* @param item The element to remove.
|
||||
* @param count The number of times to remove the element (default is 1).
|
||||
* @returns True if the element was present, false otherwise.
|
||||
*/
|
||||
remove(item: T, count = 1): boolean {
|
||||
const currentCount = this.get(item);
|
||||
if (currentCount === undefined) {
|
||||
return false;
|
||||
}
|
||||
if (currentCount <= count) {
|
||||
this.delete(item);
|
||||
} else {
|
||||
this.set(item, currentCount - count);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the count of the specified item.
|
||||
*
|
||||
* @param item The element whose count is to be retrieved.
|
||||
* @returns The number of occurrences of the element.
|
||||
*/
|
||||
count(item: T): number {
|
||||
return this.get(item) ?? 0;
|
||||
}
|
||||
}
|
||||
37
apps/web/src/routes/kripke/lib/store.ts
Normal file
37
apps/web/src/routes/kripke/lib/store.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
import { persisted } from "svelte-persisted-store";
|
||||
import type { Move } from "../components/game.svelte";
|
||||
import { MultiSet } from "./multiset";
|
||||
import { date } from "./system";
|
||||
|
||||
export type Daily = {
|
||||
date: string;
|
||||
moves: Move[];
|
||||
};
|
||||
|
||||
export const daily = persisted<Daily>(
|
||||
"daily",
|
||||
{
|
||||
date: date(),
|
||||
moves: [],
|
||||
},
|
||||
{
|
||||
syncTabs: true,
|
||||
storage: "local",
|
||||
beforeRead: (value) => {
|
||||
if (value.date !== date()) return { date: date(), moves: [] };
|
||||
return value;
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
export type FormulaHistory = MultiSet<string>;
|
||||
|
||||
export const formulaHistory = persisted<
|
||||
FormulaHistory,
|
||||
readonly [string, number][]
|
||||
>("formula-history", new MultiSet(), {
|
||||
syncTabs: true,
|
||||
storage: "local",
|
||||
beforeWrite: (val) => [...val],
|
||||
beforeRead: (val) => new MultiSet(val),
|
||||
});
|
||||
@@ -1,24 +0,0 @@
|
||||
import { persisted } from "svelte-persisted-store";
|
||||
import type { Move } from "./components/game.svelte";
|
||||
import { date } from "./lib/system";
|
||||
|
||||
export type Daily = {
|
||||
date: string;
|
||||
moves: Move[];
|
||||
};
|
||||
|
||||
export const daily = persisted<Daily>(
|
||||
"daily",
|
||||
{
|
||||
date: date(),
|
||||
moves: [],
|
||||
},
|
||||
{
|
||||
syncTabs: true,
|
||||
storage: "local",
|
||||
beforeRead: (value) => {
|
||||
if (value.date !== date()) return { date: date(), moves: [] };
|
||||
return value;
|
||||
},
|
||||
},
|
||||
);
|
||||
Reference in New Issue
Block a user