From 8930deb9ac5893712446055f9cd99300536bdb42 Mon Sep 17 00:00:00 2001 From: Nat Quayle Nelson Date: Wed, 15 Dec 2021 15:05:28 -0700 Subject: [PATCH] Store Hollywoo objects in improved FuzzyMap --- kiss/src/kiss/FuzzyMap.hx | 49 ++++++++++++++++++----- projects/hollywoo/src/hollywoo/Movie.hx | 3 +- projects/hollywoo/src/hollywoo/Movie.kiss | 15 +++---- 3 files changed, 48 insertions(+), 19 deletions(-) diff --git a/kiss/src/kiss/FuzzyMap.hx b/kiss/src/kiss/FuzzyMap.hx index 5555e678..1308f25d 100644 --- a/kiss/src/kiss/FuzzyMap.hx +++ b/kiss/src/kiss/FuzzyMap.hx @@ -4,9 +4,10 @@ import haxe.ds.StringMap; using hx.strings.Strings; +// TODO forward and implement the full Map API abstract FuzzyMap(StringMap) from StringMap to StringMap { - public inline function new(m:StringMap) { - this = m; + public inline function new(?m:StringMap) { + this = if (m != null) m else new StringMap(); } @:from @@ -19,24 +20,50 @@ abstract FuzzyMap(StringMap) from StringMap to StringMap { return this; } - @:arrayAccess - public inline function get(searchKey:String):Null { - var bestMatch:Null = null; - var bestScore = 0; + static var threshold = 0.8; + function bestMatch(fuzzySearchKey:String, ?throwIfNone=true):String { + if (this.exists(fuzzySearchKey)) return fuzzySearchKey; - for (key => value in this) { - var score = searchKey.getFuzzyDistance(key); + var bestScore = 0.0; + var bestKey = null; + + for (key in this.keys()) { + var score = 1 - (key.getLevenshteinDistance(fuzzySearchKey) / Math.max(key.length, fuzzySearchKey.length)); if (score > bestScore) { bestScore = score; - bestMatch = value; + bestKey = key; } } - return bestMatch; + if (bestScore < threshold) { + if (throwIfNone) + throw 'No good match for $fuzzySearchKey in $this -- best was $bestKey with $bestScore'; + else + return null; + } + + #if (test || debug) + trace('Fuzzy match $bestKey for $fuzzySearchKey score: $bestScore'); + #end + + return bestKey; } @:arrayAccess - public inline function set(key:String, v:T):T { + public inline function get(fuzzySearchKey:String):Null { + return this.get(bestMatch(fuzzySearchKey)); + } + + public inline function remove(fuzzySearchKey:String):Bool { + var key = bestMatch(fuzzySearchKey, false); + if (key == null) return false; + return this.remove(key); + } + + @:arrayAccess + public inline function set(fuzzySearchKey:String, v:T):T { + var key = bestMatch(fuzzySearchKey, false); + if (key == null) key = fuzzySearchKey; this.set(key, v); return v; } diff --git a/projects/hollywoo/src/hollywoo/Movie.hx b/projects/hollywoo/src/hollywoo/Movie.hx index 4f70734a..32a1e553 100644 --- a/projects/hollywoo/src/hollywoo/Movie.hx +++ b/projects/hollywoo/src/hollywoo/Movie.hx @@ -4,6 +4,7 @@ import haxe.Constraints.Function; import haxe.Timer; import kiss.AsyncEmbeddedScript; import kiss.Prelude; +import kiss.FuzzyMap; import hollywoo.Scene; import hollywoo.Director; @@ -20,5 +21,5 @@ enum DelayHandling { class Movie extends AsyncEmbeddedScript { // TODO for some reason this wasn't working when declared in Movie.kiss: // Mutable representation of frames in time: - var scenes:Map> = []; + var scenes:FuzzyMap> = new FuzzyMap>(); } diff --git a/projects/hollywoo/src/hollywoo/Movie.kiss b/projects/hollywoo/src/hollywoo/Movie.kiss index 5af12ccd..8eebbd51 100644 --- a/projects/hollywoo/src/hollywoo/Movie.kiss +++ b/projects/hollywoo/src/hollywoo/Movie.kiss @@ -2,19 +2,20 @@ (#unless subclass // Mostly immutable, reusable resources: - (prop :Map sets (new Map)) - (prop :Map actors (new Map)) - (prop :Map sounds (new Map)) - (prop :Map songs (new Map)) - (prop :Map props (new Map)) + (prop :FuzzyMap sets (new FuzzyMap)) + (prop :FuzzyMap actors (new FuzzyMap)) + (prop :FuzzyMap sounds (new FuzzyMap)) + (prop :FuzzyMap songs (new FuzzyMap)) + (prop :FuzzyMap props (new FuzzyMap)) (prop &mut :DelayHandling delayHandling AutoWithSkip) // TODO for some reason this won't work when declared in Kiss syntax: // Mutable representation of frames in time: // var scenes:Map> = []; - (prop :Map shownScenes (new Map)) - (prop :Map shownCharacters (new Map)) + + (prop :FuzzyMap shownScenes (new FuzzyMap)) + (prop :FuzzyMap shownCharacters (new FuzzyMap)) // This is set and unset by doPreload defined in HollywooDSL.kiss (prop &mut isLoading false)