From 686801e0e520ebd1473a13cb9ca03a55d980d3e2 Mon Sep 17 00:00:00 2001 From: Ben Wirth Date: Sat, 2 Nov 2024 02:15:48 -0700 Subject: [PATCH 1/2] test cases for decks which currently fail on master - See https://github.com/benw10-1/STR-Spire-Mod/commit/3933f953a1475641ead42064cd443a1ef9ed032e on the mod repo for generating deck strings from the mod output without needed to launch STS - includes case from running STS with the mod manually and getting the output directly from there --- backend/api/deck_test.go | 90 +++++++++++++++++++++++++++++ backend/api/testdata/breaking-1.txt | 1 + backend/api/testdata/breaking-2.txt | 1 + 3 files changed, 92 insertions(+) create mode 100644 backend/api/testdata/breaking-1.txt create mode 100644 backend/api/testdata/breaking-2.txt diff --git a/backend/api/deck_test.go b/backend/api/deck_test.go index 4b11e6c..bf3edb0 100644 --- a/backend/api/deck_test.go +++ b/backend/api/deck_test.go @@ -2,9 +2,14 @@ package api import ( "fmt" + "io" + "net/http/httptest" + "os" "strings" + "sync" "testing" + "github.com/gin-gonic/gin" "gotest.tools/v3/assert" ) @@ -91,6 +96,91 @@ func TestDecompress(t *testing.T) { } } +func TestDecompressIntegration(t *testing.T) { + // cases straight from mod output + testCases := []struct { + desc string + inputFile string + }{ + { + desc: "Very large deck", + inputFile: "testdata/breaking-1.txt", + }, + { + desc: "Another very large deck", + inputFile: "testdata/breaking-2.txt", + }, + } + + for _, tc := range testCases { + t.Run(tc.desc, func(t *testing.T) { + inpFile, err := os.Open(tc.inputFile) + assert.NilError(t, err) + defer inpFile.Close() + + inp, err := io.ReadAll(inpFile) + assert.NilError(t, err) + + actualOutput, err := decompress(string(inp)) + assert.NilError(t, err) + + // should be no & symbols + assert.Equal(t, strings.Contains(actualOutput, "&"), false, actualOutput) + }) + } +} + +// trying to replicate JSON escape HTML issue +func TestDecompressAPIIntegration(t *testing.T) { + // cases straight from mod output + testCases := []struct { + desc string + inputFile string + }{ + { + desc: "Very large deck", + inputFile: "testdata/breaking-1.txt", + }, + { + desc: "Another very large deck", + inputFile: "testdata/breaking-2.txt", + }, + } + + apiHandler := &API{ + deckLists: make(map[string]string), + deckLock: &sync.RWMutex{}, + } + + for _, tc := range testCases { + t.Run(tc.desc, func(t *testing.T) { + inpFile, err := os.Open(tc.inputFile) + assert.NilError(t, err) + defer inpFile.Close() + + inp, err := io.ReadAll(inpFile) + assert.NilError(t, err) + + apiHandler.deckLists["test"] = string(inp) + + respW := httptest.NewRecorder() + testCtx, _ := gin.CreateTestContext(respW) + testCtx.Params = gin.Params{ + {Key: "name", Value: "test"}, + } + + apiHandler.getDeckHandler(testCtx) + + assert.Equal(t, respW.Code, 200) + + actualOutput := respW.Body.String() + + // should be no & symbols + assert.Equal(t, strings.Contains(actualOutput, "&"), false, actualOutput) + }) + } +} + func TestParseCommaDelimitedIntegerArray(t *testing.T) { testCases := []struct { desc string diff --git a/backend/api/testdata/breaking-1.txt b/backend/api/testdata/breaking-1.txt new file mode 100644 index 0000000..a8eeccf --- /dev/null +++ b/backend/api/testdata/breaking-1.txt @@ -0,0 +1 @@ +damage|#yBlock|#yExhaust|Deal|your|.;;|card|cards|Gain|#yVulnerable|#yPoison|Whenever|discard|Apply|turn|this|additional|enemies|hand|pile|combat|#yLightning|Draw|gain|random|into|played|the|from|#yChannel|times|draw|#yWeak|Attack|you|enemy|start|#yRetain|increase|Energy|Double|#yEthereal|attack|Attacks|Discard|twice|each|discarded|creatures|#yScry|number|play|#yStance|Strike|#yIntangible|have|#yShivs|[E]|receive|#yDexterity|Permanently|Costs|apply|equal|first|for|ALL|Unplayable|Poison|#yStrength|next|lose|#yUpgraded|Vulnerable|#g4|#yUpgrade|unblocked|Dexterity|Put|#g2|Form|#g10|and|Strength|copy|only|#yFatal|#g7||0,1,2,2,2,3,4,4,5,6,6,7,8,9,10,11,11,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,13,14,14,14,15,16,17,18,19,20,21,21,21,22,23,24,25,25,26,27,28,29,29,29,30,31,32,33,34,34,34,35,35,36,37,37,38,39,40,41,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,43,44,45,46,46,46,47,48,48,48,49,50,51,52,53,54,54,54,55,56,57,58,59;;;Acrobatics;0;-;-1;-1;+;0;-;&m &* &6s. NL Dis&6 1 &6.;-;1;1;1;2;1;&m 3 &6s. NL Dis&6 1 &6&5Anger;0;-;-1;-1;+;0;-;&3 #g8 &0. NL Add a &' of &f &6 NL &p &4 dis&6 &j.;-;0;0;0;2;0;&3 6 &0. NL Add a &' of &f &6 NL &p &4 dis&6 &j&5Apo&rosis;0;-;-1;-1;+;0;0,1;&: &% &4 NL &6s &^ &r rest of NL &k. NL &2.;0,1;2;1;1;4;4;&: &% &4 NL &6s &^ &r rest of NL &k. NL &2&5Auto-Shields;0;-;-1;-1;+;0;2;If &z &V no &1, NL &n #g15 &1.;2;1;1;1;3;2;If &z &V no &1, NL &n 11 &1&5Backflip;0;-;-1;-1;+;0;2;&8 #g8 &1. NL &m 2 &6s.;2;1;1;1;2;1;&8 5 &1. NL &m 2 &6s&5Bash;0;-;-1;-1;+;0;3;&3 &# &0. NL &d #g3 &9.;3;2;2;0;0;0;&3 8 &0. NL &d 2 &9&5Blade Dance;0;-;60;60;+;0;-;Add &* &W &p &4 NL &i.;-;1;1;1;2;1;Add 3 &W &p &4 NL &i&5Bouncing Flask;0;-;-1;-1;+;0;4;&d 3 &a to a NL &o &A &* NL &v.;4;2;2;1;3;1;&d 3 &a to a NL &o &A 3 NL &v&5Clash;0;-;-1;-1;+;0;-;Can &{ be &q if NL every &6 in &4 NL &i is an &y. NL &3 #g18 &0.;-;0;0;0;2;0;Can &{ be &q if NL every &6 in &4 NL &i is an &y. NL &3 14 &0&5Cloak &$ Dagger;0;-;60;60;+;0;2;&8 6 &1. NL Add &( &W &p &4 NL &i.;2;1;1;1;2;1;&8 6 &1. NL Add 1 #yShiv &p &4 NL &i&5Com&j Driver;0;-;-1;-1;+;0;-;&3 &# &0. NL &m 1 &6 &^ &L NL unique Orb &z &V.;-;1;1;0;2;2;&3 7 &0. NL &m 1 &6 &^ &L NL unique Orb &z &V&5Consecrate;0;-;-1;-1;+;0;-;&3 #g8 &0 to &% NL &h.;-;0;0;0;2;3;&3 5 &0 to &% NL &h&5Crippling Cloud;0;-;-1;-1;+;0;4,5,1;&d &~ &a &$ 2 NL &x to &% &h. NL &2.;4,5,1;2;2;1;3;1;&d 4 &a &$ 2 NL &x to &% &h. NL &2&5Deadly &@;0;-;-1;-1;+;0;4;&d &~ &a.;4;1;1;1;2;1;&d 5 &a&5Defend;0;-;-1;-1;+;0;2;&8 #g8 &1.;2;1;1;1;0;2;&8 5 &1&5Deflect;0;-;-1;-1;+;0;2;&8 &~ &1.;2;0;0;1;2;1;&8 4 &1&5Demon &);0;-;-1;-1;+;0;6;At &r &B of &4 NL &e, &n #g3 &>.;6;3;3;2;4;0;At &r &B of &4 NL &e, &n 2 &>&5Deva &);0;-;-1;-1;+;0;8;At &r &B of &4 NL &e, &n &X NL &$ &D &f &n NL by !M!.;7,8;3;3;2;4;3;#yE&rreal. NL At &r &B of &4 NL &e, &n &X NL &$ &D &f &n NL by !M!&5&F &E;0;-;-1;-1;+;0;1;&F &4 &E. NL &2.;1;1;0;1;3;2;&F &4 &E. NL &2&5Echo &);0;-;-1;-1;+;0;-;The &/ &6 &z &Q NL &L &e is &q NL &K.;7;3;3;2;4;2;#yE&rreal. NL The &/ &6 &z &Q NL &L &e is &q NL &K&5Empty Fist;0;-;-1;-1;+;0;9;&3 #g14 &0. NL Exit &4 &R.;9;1;1;0;2;3;&3 9 &0. NL Exit &4 &R&5Endless Agony;0;-;-1;-1;+;0;1;&3 #g6 &0. NL &b &z &w NL &f &6, add a &' of NL it &p &4 &i. NL &2.;1;0;0;0;3;1;&3 4 &0. NL &b &z &w NL &f &6, add a &' of NL it &p &4 &i. NL &2&5Entrench;0;-;-1;-1;+;0;2;&F &4 &1.;2;2;1;1;3;0;&F &4 &1&5Eruption;0;-;-1;-1;+;0;10;&3 9 &0. NL Enter #yWrath.;10;2;1;0;0;3;&3 9 &0. NL Enter #yWrath&5Eviscerate;0;-;-1;-1;+;0;8;&` 1 less &X NL &^ &L &6 dis&6ed NL &f &e. NL &3 #g9 &0 3 &v.;8;3;3;0;3;1;&` 1 less &X NL &^ &L &6 dis&6ed NL &f &e. NL &3 7 &0 3 &v&5Flying Sleeves;0;-;-1;-1;+;0;11;&C. NL &3 #g6 &0 &K.;11;1;1;0;2;3;&C. NL &3 4 &0 &K&5Follow-Up;0;-;-1;-1;+;0;8;&3 #g11 &0. NL If &r last &6 &q NL &f &k was an NL &y, &n &X.;8;1;1;0;2;3;&3 7 &0. NL If &r last &6 &q NL &f &k was an NL &y, &n &X&5Genetic Algorithm;0;-;-1;-1;+;0;2,1;&8 1 &1. NL &_ &D NL &f &6's &1 by NL !M!. NL &2.;2,1;1;1;1;3;2;&8 1 &1. NL &_ &D NL &f &6's &1 by NL !M!. NL &2&5Go &^ &r Eyes;0;-;-1;-1;+;0;5;&3 &* &0. NL If &r &A intends to NL &H, &[ &( &x.;5;0;0;0;2;2;&3 3 &0. NL If &r &A intends to NL &H, &[ 1 &x&5H&$ of Greed;0;-;-1;-1;+;0;12;&3 &(5 &0. NL If &}, &n &(5 Gold.;12;2;2;0;4;4;&3 20 &0. NL If &}, &n 20 Gold&5Headbutt;0;-;-1;-1;+;0;-;&3 #g12 &0. NL &. a &6 &s &4 NL dis&6 &j on top of NL &4 &w &j.;-;1;1;0;2;0;&3 9 &0. NL &. a &6 &s &4 NL dis&6 &j on top of NL &4 &w &j&5Heatsinks;0;-;-1;-1;+;0;-;&b &z &Q a NL Power &6, &w &( NL &6s.;-;1;1;2;3;2;&b &z &Q a NL Power &6, &w 1 NL &6&5Hologram;0;-;-1;-1;+;0;2;&8 #g5 &1. NL &. a &6 &s &4 NL dis&6 &j &p &4 NL &i.;2,1;1;1;1;2;2;&8 3 &1. NL &. a &6 &s &4 NL dis&6 &j &p &4 NL &i. NL &2&5Iron Wave;0;-;-1;-1;+;0;2;&8 &~ &1. NL &3 &~ &0.;2;1;1;0;2;0;&8 5 &1. NL &3 5 &0&5Master of Strategy;0;-;-1;-1;+;0;1;&m &* &6s. NL &2.;1;0;0;1;4;4;&m 3 &6s. NL &2&5Masterful Stab;0;-;-1;-1;+;0;8;&` 1 &g &X NL &^ &L time &z &= NL HP &f &k. NL &3 #g16 &0.;8;0;0;0;3;1;&` 1 &g &X NL &^ &L time &z &= NL HP &f &k. NL &3 12 &0&5Nirvana;0;-;-1;-1;+;0;13,2;&b &z &O, NL &n &* &1.;13,2;1;1;2;3;3;&b &z &O, NL &n 3 &1&5Noxious Fumes;0;-;-1;-1;+;0;4;At &r &B of &4 NL &e, &[ #g3 &a NL to &% &h.;4;1;1;2;3;1;At &r &B of &4 NL &e, &[ 2 &a NL to &% &h&5Pommel &S;0;-;-1;-1;+;0;-;&3 &# &0. NL &m &( &6s.;-;1;1;0;2;0;&3 9 &0. NL &m 1 &6&5Protect;0;-;-1;-1;+;0;11,2;&C. NL &8 #g16 &1.;11,2;2;2;1;2;3;&C. NL &8 12 &1&5Rebound;0;-;-1;-1;+;0;-;&3 #g12 &0. NL &. &r &< &6 &z NL &Q &f &e on top of NL &4 &w &j.;-;1;1;0;2;2;&3 9 &0. NL &. &r &< &6 &z NL &Q &f &e on top of NL &4 &w &j&5Recycle;0;-;-1;-1;+;0;1,8;&2 a &6. NL &8 &X &] to its NL cost.;1,8;1;0;1;3;2;&2 a &6. NL &8 &X &] to its NL cost&5Searing Blow+2000;0;-;-1;-1;Searing Blow+2001;2000;_;&3 &(009016 &0. NL Can be &- any NL &P of &v.;0;2;2;0;3;0;&3 &(007012 &0. NL Can be &- any NL &P of &v&5Shrug It Off;0;-;-1;-1;+;0;2;&8 #g11 &1. NL &m 1 &6.;2;1;1;1;2;0;&8 8 &1. NL &m 1 &6&5Stack;0;-;-1;-1;+;0;2;&8 &1 &] to &r NL &P of &6s in NL &4 dis&6 &j +3.;2;1;1;1;2;2;&8 &1 &] to &r NL &P of &6s in NL &4 dis&6 &j&5Static Discharge;0;-;-1;-1;+;0;14,15;&b &z &Y NL &; &H NL &0, &t &( NL &l.;14,15;1;1;2;3;2;&b &z &Y NL &; &H NL &0, &t 1 NL &l&5&S;0;-;-1;-1;+;0;-;&3 #g9 &0.;-;1;1;0;0;3;&3 6 &0&5Survivor;0;-;-1;-1;+;0;2;&8 #g11 &1. NL Dis&6 1 &6.;2;1;1;1;0;1;&8 8 &1. NL Dis&6 1 &6&5Swift &S;0;-;-1;-1;+;0;-;&3 &# &0.;-;0;0;0;3;4;&3 7 &0&5Sword Boomerang;0;-;-1;-1;+;0;-;&3 3 &0 to a NL &o &A &* NL &v.;-;1;1;0;2;0;&3 3 &0 to a NL &o &A 3 NL &v&5Terror;0;-;-1;-1;+;0;3,1;&d 99 &9. NL &2.;3,1;1;0;1;3;1;&d 99 &9. NL &2&5Third Eye;0;-;-1;-1;+;0;2,13;&8 #g9 &1. NL &O !M!.;2,13;1;1;1;2;3;&8 7 &1. NL &O !M!&5Twin &S;0;-;-1;-1;+;0;-;&3 &~ &0 &K.;-;1;1;0;2;0;&3 5 &0 &K&5Uppercut;0;-;-1;-1;+;0;5,3;&3 13 &0. NL &d &( &x. NL &d &( &9.;5,3;2;2;0;3;0;&3 13 &0. NL &d 1 &x. NL &d 1 &9&5Violence;0;-;-1;-1;+;0;1;&. &* &o &ys NL &s &4 &w &j NL &p &4 &i. NL &2.;1;0;0;1;4;4;&. 3 &o &ys NL &s &4 &w &j NL &p &4 &i. NL &2&5Wheel Kick;0;-;-1;-1;+;0;-;&3 &(0 &0. NL &m 2 &6s.;-;2;2;0;3;3;&3 15 &0. NL &m 2 &6s&5Wraith &);0;-;-1;-1;+;0;16,17;&8 #g3 &T. NL At &r end of &4 NL &e, &= 1 &Z.;16,17;3;3;2;4;1;&8 2 &T. NL At &r end of &4 NL &e, &= 1 &Z&5Wreath of Flame;0;-;-1;-1;+;0;-;Your &< &y deals NL #g8 &g &0.;-;1;1;1;3;3;Your &< &y deals NL 5 &g &0&5Zap;0;-;-1;-1;+;0;14,15;&t 1 &l.;14,15;1;0;1;0;2;&t 1 &l&5Ascender's Bane;0;-;-1;-1;-;0;-;-;18,7;-2;-2;4;1;5;#yUn&Qable. NL #yE&rreal. NL Cannot be removed NL &s &4 deck&5Shiv;0;-;-1;-1;+;0;1;&3 #g6 &0. NL &2.;1;0;0;0;1;4;&3 4 &0. NL &2&5;Upgrade;Upgrading &6s makes &rm more powerful. Cards can &{ be upgraded once&5Exhaust;Removed until end of &k&5Block;Until &< &e, prevents &0&5&+;&+ &N take #b50% more &0 &s &ys&5&@;&@ed &N &= HP at &r &B of &rir &e. Each &e, &@ is reduced by #b1&5Weak;Weakened &N deal #b25% less &0 with &ys&5&!;&! adds &g &0 to &Hs&5E&rreal;If &f &6 is in &4 &i at &r end of &e, it is exhausted. Exhausted &6s are removed &s &4 deck until &r end of &k&5&X &E;&E is used to &Q &6s &s &4 &i&5Stance;You can &{ &V one stance at a time&5Wrath;In &f &R, &z deal &$ &Y double &H &0&5Retain;Retained &6s are not dis&6ed at &r end of &e&5Fatal;Triggers whenever &f &6 kills a non-minion &A&5Scry;Look at &r top X &6s of &4 &w &j. You may dis&6 any of &rm&5Channel;Channeling an Orb puts it &p &4 &/ empty slot. If &z &V no empty slots, &4 &/ Orb is automatically #yEvoked to make room&5Lightning;Orb: &3s &0 to &o &h&5Intangible;Reduce &% &0 taken &$ HP loss to #b1&5&,;&, improves Block &ned &s &6s&5Un&Qable;Un&Qable &6s cannot be &q &s &4 &i. \ No newline at end of file diff --git a/backend/api/testdata/breaking-2.txt b/backend/api/testdata/breaking-2.txt new file mode 100644 index 0000000..8578231 --- /dev/null +++ b/backend/api/testdata/breaking-2.txt @@ -0,0 +1 @@ +damage|#yBlock|#yExhaust|Deal|your|.;;|card|Gain|cards|#yVulnerable|#yPoison|Whenever|discard|Apply|turn|this|additional|enemies|hand|pile|combat|#yLightning|Draw|gain|random|into|played|the|from|#yChannel|times|draw|#yWeak|Strike|Attack|you|enemy|start|#yRetain|increase|Energy|Double|#yEthereal|attack|Attacks|Discard|twice|each|discarded|creatures|#yScry|number|play|#yStance|#yIntangible|have|#yShivs|[E]|receive|#yDexterity|Permanently|Costs|apply|equal|first|for|ALL|Unplayable|Poison|#yStrength|next|Defend|lose|#yUpgraded|Vulnerable|#g4|#yUpgrade|unblocked|Dexterity|Put|#g2|#g8|Form|#g10|and|Strength|copy|only||0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,33,34,35,36,33,37,18,38,39,40,41,42,37,39,43,44,45,46,47,48,49,50,51,25,29,52,53,54,49,55,56,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,58,58,58,59,59,59,60,60,60,61,61,61,62,62,62,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63;;;Demon &$;0;-;-1;-1;+;0;0;At &r &C of &4 NL &e, &n #g3 &>.;0;3;3;2;4;0;At &r &C of &4 NL &e, &n 2 &>&5Wraith &$;0;-;-1;-1;+;0;1,2;&7 #g3 &T. NL At &r end of &4 NL &e, &- 1 &Z.;1,2;3;3;2;4;1;&7 2 &T. NL At &r end of &4 NL &e, &- 1 &Z&5Echo &$;0;-;-1;-1;+;0;-;The &/ &6 &A &R NL &M &e is &q NL &L.;3;3;3;2;4;2;#yE&rreal. NL The &/ &6 &A &R NL &M &e is &q NL &L&5Deva &$;0;-;-1;-1;+;0;4;At &r &C of &4 NL &e, &n &X NL &' &E &f &n NL by !M!.;3,4;3;3;2;4;3;#yE&rreal. NL At &r &C of &4 NL &e, &n &X NL &' &E &f &n NL by !M!&5Ascender's Bane;0;-;-1;-1;-;0;-;-;5,3;-2;-2;4;1;5;#yUn&Rable. NL #yE&rreal. NL Cannot be removed NL &s &4 deck&5Bash;0;-;-1;-1;+;0;6;&3 &! &0. NL &d #g3 &9.;6;2;2;0;0;0;&3 8 &0. NL &d 2 &9&5Survivor;0;-;-1;-1;+;0;7;&7 #g11 &1. NL Dis&6 1 &6.;7;1;1;1;0;1;&7 8 &1. NL Dis&6 1 &6&5Zap;0;-;-1;-1;+;0;8,9;&t 1 &l.;8,9;1;0;1;0;2;&t 1 &l&5Eruption;0;-;-1;-1;+;0;10;&3 9 &0. NL Enter #yWrath.;10;2;1;0;0;3;&3 9 &0. NL Enter #yWrath&5&y;0;-;-1;-1;+;0;-;&3 #g9 &0.;-;1;1;0;0;0;&3 6 &0&5&y;0;-;-1;-1;+;0;-;&3 #g9 &0.;-;1;1;0;0;1;&3 6 &0&5&y;0;-;-1;-1;+;0;-;&3 #g9 &0.;-;1;1;0;0;2;&3 6 &0&5&=;0;-;-1;-1;+;0;7;&7 &# &1.;7;1;1;1;0;0;&7 5 &1&5&=;0;-;-1;-1;+;0;7;&7 &# &1.;7;1;1;1;0;1;&7 5 &1&5&=;0;-;-1;-1;+;0;7;&7 &# &1.;7;1;1;1;0;3;&7 5 &1&5Wreath of Flame;0;-;-1;-1;+;0;-;Your &< &z deals NL &# &g &0.;-;1;1;1;3;3;Your &< &z deals NL 5 &g &0&5Wheel Kick;0;-;-1;-1;+;0;-;&3 &)0 &0. NL &m 2 &6s.;-;2;2;0;3;3;&3 15 &0. NL &m 2 &6s&5Com&j Driver;0;-;-1;-1;+;0;-;&3 &! &0. NL &m 1 &6 &^ &M NL unique Orb &A &V.;-;1;1;0;2;2;&3 7 &0. NL &m 1 &6 &^ &M NL unique Orb &A &V&5Consecrate;0;-;-1;-1;+;0;-;&3 &# &0 to &% NL &h.;-;0;0;0;2;3;&3 5 &0 to &% NL &h&5Auto-Shields;0;-;-1;-1;+;0;7;If &A &V no &1, NL &n #g15 &1.;7;1;1;1;3;2;If &A &V no &1, NL &n 11 &1&5Genetic Algorithm;0;-;-1;-1;+;0;7,11;&7 1 &1. NL &_ &E NL &f &6's &1 by !M!. NL &2.;7,11;1;1;1;3;2;&7 1 &1. NL &_ &E NL &f &6's &1 by !M!. NL &2&5Eviscerate;0;-;-1;-1;+;0;4;&` 1 less &X NL &^ &M &6 dis&6ed NL &f &e. NL &3 #g9 &0 3 &v.;4;3;3;0;3;1;&` 1 less &X NL &^ &M &6 dis&6ed NL &f &e. NL &3 7 &0 3 &v&5Bouncing Flask;0;-;-1;-1;+;0;12;&d 3 &a to a NL &o &B &: NL &v.;12;2;2;1;3;1;&d 3 &a to a NL &o &B 3 NL &v&5Twin &y;0;-;-1;-1;+;0;-;&3 #g7 &0 &L.;-;1;1;0;2;0;&3 5 &0 &L&5Static Discharge;0;-;-1;-1;+;0;8,9;&b &A &Y NL &, &I NL &0, &t &) NL &l.;8,9;1;1;2;3;2;&b &A &Y NL &, &I NL &0, &t 1 NL &l&5Noxious Fumes;0;-;-1;-1;+;0;12;At &r &C of &4 NL &e, &[ #g3 &a to NL &% &h.;12;1;1;2;3;1;At &r &C of &4 NL &e, &[ 2 &a to NL &% &h&5Terror;0;-;-1;-1;+;0;6,11;&d 99 &9. NL &2.;6,11;1;0;1;3;1;&d 99 &9. NL &2&5Nirvana;0;-;-1;-1;+;0;13,7;&b &A &P, NL &n &: &1.;13,7;1;1;2;3;3;&b &A &P, NL &n 3 &1&5Pommel &y;0;-;-1;-1;+;0;-;&3 &! &0. NL &m &) &6s.;-;1;1;0;2;0;&3 9 &0. NL &m 1 &6&5Blade Dance;0;-;64;64;+;0;-;Add &: &W &p &4 NL &i.;-;1;1;1;2;1;Add 3 &W &p &4 NL &i&5Entrench;0;-;-1;-1;+;0;7;&G &4 &1.;7;2;1;1;3;0;&G &4 &1&5Rebound;0;-;-1;-1;+;0;-;&3 #g12 &0. NL &( &r &< &6 &A NL &R &f &e on top of NL &4 &w &j.;-;1;1;0;2;2;&3 9 &0. NL &( &r &< &6 &A NL &R &f &e on top of NL &4 &w &j&5Heatsinks;0;-;-1;-1;+;0;-;&b &A &R a NL Power &6, &w &) NL &6s.;-;1;1;2;3;2;&b &A &R a NL Power &6, &w 1 NL &6&5Endless Agony;0;-;-1;-1;+;0;11;&3 #g6 &0. NL &b &A &w NL &f &6, add a &} of NL it &p &4 &i. NL &2.;11;0;0;0;3;1;&3 4 &0. NL &b &A &w NL &f &6, add a &} of NL it &p &4 &i. NL &2&5Cloak &' Dagger;0;-;64;64;+;0;7;&7 6 &1. NL Add &) &W &p &4 NL &i.;7;1;1;1;2;1;&7 6 &1. NL Add 1 #yShiv &p &4 NL &i&5Protect;0;-;-1;-1;+;0;14,7;&D. NL &7 #g16 &1.;14,7;2;2;1;2;3;&D. NL &7 12 &1&5Go &^ &r Eyes;0;-;-1;-1;+;0;15;&3 &: &0. NL If &r &B intends to NL &I, &[ &) &x.;15;0;0;0;2;2;&3 3 &0. NL If &r &B intends to NL &I, &[ 1 &x&5Masterful Stab;0;-;-1;-1;+;0;4;&` 1 &g &X NL &^ &M time &A &- NL HP &f &k. NL &3 #g16 &0.;4;0;0;0;3;1;&` 1 &g &X NL &^ &M time &A &- NL HP &f &k. NL &3 12 &0&5Empty Fist;0;-;-1;-1;+;0;16;&3 #g14 &0. NL Exit &4 &S.;16;1;1;0;2;3;&3 9 &0. NL Exit &4 &S&5Backflip;0;-;-1;-1;+;0;7;&7 &# &1. NL &m 2 &6s.;7;1;1;1;2;1;&7 5 &1. NL &m 2 &6s&5Third Eye;0;-;-1;-1;+;0;7,13;&7 #g9 &1. NL &P !M!.;7,13;1;1;1;2;3;&7 7 &1. NL &P !M!&5Recycle;0;-;-1;-1;+;0;11,4;&2 a &6. NL &7 &X &] to its NL cost.;11,4;1;0;1;3;2;&2 a &6. NL &7 &X &] to its NL cost&5&G &F;0;-;-1;-1;+;0;11;&G &4 &F. NL &2.;11;1;0;1;3;2;&G &4 &F. NL &2&5Headbutt;0;-;-1;-1;+;0;-;&3 #g12 &0. NL &( a &6 &s &4 NL dis&6 &j on top of NL &4 &w &j.;-;1;1;0;2;0;&3 9 &0. NL &( a &6 &s &4 NL dis&6 &j on top of NL &4 &w &j&5Uppercut;0;-;-1;-1;+;0;15,6;&3 13 &0. NL &d &) &x. NL &d &) &9.;15,6;2;2;0;3;0;&3 13 &0. NL &d 1 &x. NL &d 1 &9&5Stack;0;-;-1;-1;+;0;7;&7 &1 &] to &r NL &Q of &6s in NL &4 dis&6 &j +3.;7;1;1;1;2;2;&7 &1 &] to &r NL &Q of &6s in NL &4 dis&6 &j&5Deadly &@;0;-;-1;-1;+;0;12;&d #g7 &a.;12;1;1;1;2;1;&d 5 &a&5Shrug It Off;0;-;-1;-1;+;0;7;&7 #g11 &1. NL &m 1 &6.;7;1;1;1;2;0;&7 8 &1. NL &m 1 &6&5Clash;0;-;-1;-1;+;0;-;Can &~ be &q if NL every &6 in &4 NL &i is an &z. NL &3 #g18 &0.;-;0;0;0;2;0;Can &~ be &q if NL every &6 in &4 NL &i is an &z. NL &3 14 &0&5Flying Sleeves;0;-;-1;-1;+;0;14;&D. NL &3 #g6 &0 &L.;14;1;1;0;2;3;&D. NL &3 4 &0 &L&5Follow-Up;0;-;-1;-1;+;0;4;&3 #g11 &0. NL If &r last &6 &q NL &f &k was an NL &z, &n &X.;4;1;1;0;2;3;&3 7 &0. NL If &r last &6 &q NL &f &k was an NL &z, &n &X&5Acrobatics;0;-;-1;-1;+;0;-;&m &: &6s. NL Dis&6 1 &6.;-;1;1;1;2;1;&m 3 &6s. NL Dis&6 1 &6&5Anger;0;-;-1;-1;+;0;-;&3 &# &0. NL Add a &} of &f &6 NL &p &4 dis&6 &j.;-;0;0;0;2;0;&3 6 &0. NL Add a &} of &f &6 NL &p &4 dis&6 &j&5Iron Wave;0;-;-1;-1;+;0;7;&7 #g7 &1. NL &3 #g7 &0.;7;1;1;0;2;0;&7 5 &1. NL &3 5 &0&5Hologram;0;-;-1;-1;+;0;7;&7 #g5 &1. NL &( a &6 &s &4 NL dis&6 &j &p &4 NL &i.;7,11;1;1;1;2;2;&7 3 &1. NL &( a &6 &s &4 NL dis&6 &j &p &4 NL &i. NL &2&5Deflect;0;-;-1;-1;+;0;7;&7 #g7 &1.;7;0;0;1;2;1;&7 4 &1&5Sword Boomerang;0;-;-1;-1;+;0;-;&3 3 &0 to a NL &o &B &: NL &v.;-;1;1;0;2;0;&3 3 &0 to a NL &o &B 3 NL &v&5Crippling Cloud;0;-;-1;-1;+;0;12,15,11;&d #g7 &a &' 2 NL &x to &% &h. NL &2.;12,15,11;2;2;1;3;1;&d 4 &a &' 2 NL &x to &% &h. NL &2&5Violence;0;-;-1;-1;+;0;11;&( &: &o &zs NL &s &4 &w &j NL &p &4 &i. NL &2.;11;0;0;1;4;4;&( 3 &o &zs NL &s &4 &w &j NL &p &4 &i. NL &2&5H&' of Greed;0;-;-1;-1;+;0;17;&3 &)5 &0. NL If #yFatal, &n &)5 Gold.;17;2;2;0;4;4;&3 20 &0. NL If #yFatal, &n 20 Gold&5Swift &y;0;-;-1;-1;+;0;-;&3 &! &0.;-;0;0;0;3;4;&3 7 &0&5Apo&rosis;0;-;-1;-1;+;0;18,11;&; &% &4 NL &6s &^ &r rest of NL &k. NL &2.;18,11;2;1;1;4;4;&; &% &4 NL &6s &^ &r rest of NL &k. NL &2&5Master of Strategy;0;-;-1;-1;+;0;11;&m &: &6s. NL &2.;11;0;0;1;4;4;&m 3 &6s. NL &2&5Searing Blow+2000;0;-;-1;-1;Searing Blow+2001;2000;_;&3 &)009016 &0. NL Can be &+ any NL &Q of &v.;18;2;2;0;3;0;&3 2007012 &0. NL Can be &+ any NL &Q of &v&5Shiv;0;-;-1;-1;+;0;11;&3 #g6 &0. NL &2.;11;0;0;0;1;4;&3 4 &0. NL &2&5;&{;&{ adds &g &0 to &Is&5Intangible;Reduce &% &0 taken &' HP loss to #b1&5&.;&. improves Block &ned &s &6s&5E&rreal;If &f &6 is in &4 &i at &r end of &e, it is exhausted. Exhausted &6s are removed &s &4 deck until &r end of &k&5&X &F;&F is used to &R &6s &s &4 &i&5Un&Rable;Un&Rable &6s cannot be &q &s &4 &i&5&*;&* &O take #b50% more &0 &s &zs&5Block;Until &< &e, prevents &0&5Channel;Channeling an Orb puts it &p &4 &/ empty slot. If &A &V no empty slots, &4 &/ Orb is automatically #yEvoked to make room&5Lightning;Orb: &3s &0 to &o &h&5Wrath;In &f &S, &A deal &' &Y double &I &0&5Exhaust;Removed until end of &k&5&@;&@ed &O &- HP at &r &C of &rir &e. Each &e, &@ is reduced by #b1&5Scry;Look at &r top X &6s of &4 &w &j. You may dis&6 any of &rm&5Retain;Not dis&6ed at &r end of &4 &e&5Weak;Weakened &O deal #b25% less &0 with &zs&5Stance;You can &~ &V one stance at a time&5Fatal;Triggers whenever &f &6 kills a non-minion &B&5Upgrade;Upgrading &6s makes &rm more powerful. Cards can &~ be upgraded once. From 09029e0f489631d1e6318904aa624453f6f666ee Mon Sep 17 00:00:00 2001 From: Ben Wirth Date: Sat, 2 Nov 2024 02:31:36 -0700 Subject: [PATCH 2/2] go api: fix regexp escape missing wildcard characters - Fix issue where regexp escape causes wildcards to be missed. It happens in extreme-ish cases where the compressed deck string has more than 62 words and "regexp escaped" wildcards start to be used as tokens. By replacing each token using string replacement we don't need to escape thus never run into this issue. --- backend/api/deck.go | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/backend/api/deck.go b/backend/api/deck.go index fed8641..c0b70a2 100644 --- a/backend/api/deck.go +++ b/backend/api/deck.go @@ -4,7 +4,6 @@ import ( "encoding/json" "errors" "fmt" - "regexp" "strings" "github.com/gin-gonic/gin" @@ -60,11 +59,6 @@ func (a *API) getDeckHandler(c *gin.Context) { c.Data(200, "text/plain", []byte(result.String())) } -func escapeRegexp(s string) string { - r := regexp.MustCompile(`[-\/\\^$*+?.()|[\]{}]`) - return r.ReplaceAllString(s, "\\$&") -} - func decompress(s string) (string, error) { parts := strings.Split(s, "||") if len(parts) < 2 { @@ -77,11 +71,7 @@ func decompress(s string) (string, error) { for i := len(compressionDict) - 1; i >= 0; i-- { word := compressionDict[i] wildCard := fmt.Sprintf("&%c", WILDCARDS[i]) - r, err := regexp.Compile(escapeRegexp(wildCard)) - if err != nil { - return "", err - } - text = r.ReplaceAllString(text, word) + text = strings.ReplaceAll(text, wildCard, word) } return text, nil }