From afcfd095371747e5619b335f8cbf67f2da0e873f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 18 Nov 2025 17:37:06 +0000 Subject: [PATCH] Docs: Update benchmark results --- results.json | 141 +++++++++--------- .../anthropic_claude-sonnet-4.5 TEMP_0.7.js | 14 ++ .../outputs/google_gemini-2.5-pro.js | 19 +++ .../outputs/google_gemini-3-pro-preview.js | 7 + .../outputs/moonshotai_kimi-k2-thinking.js | 7 + .../outputs/openai_gpt-5.1-codex.js | 9 ++ .../openrouter_sherlock-think-alpha.js | 2 + .../anthropic_claude-sonnet-4.5 TEMP_0.7.js | 14 ++ .../outputs/google_gemini-2.5-pro.js | 18 +++ .../outputs/google_gemini-3-pro-preview.js | 13 ++ .../outputs/moonshotai_kimi-k2-thinking.js | 12 ++ .../outputs/openai_gpt-5.1-codex.js | 8 + .../openrouter_sherlock-think-alpha.js | 8 + .../anthropic_claude-sonnet-4.5 TEMP_0.7.js | 27 ++-- .../outputs/google_gemini-2.5-pro.js | 36 +++-- .../outputs/google_gemini-3-pro-preview.js | 19 +++ .../outputs/moonshotai_kimi-k2-thinking.js | 41 ++--- .../1_dijkstra/outputs/openai_gpt-5.1-chat.js | 23 --- .../outputs/openai_gpt-5.1-codex.js | 36 +++-- .../outputs/openrouter_sherlock-dash-alpha.js | 20 --- .../openrouter_sherlock-think-alpha.js | 21 +-- .../anthropic_claude-sonnet-4.5 TEMP_0.7.js | 2 +- .../outputs/google_gemini-2.5-pro.js | 42 +++--- .../outputs/google_gemini-3-pro-preview.js | 22 +++ .../outputs/moonshotai_kimi-k2-thinking.js | 41 +++-- .../outputs/openai_gpt-5.1-chat.js | 20 --- .../outputs/openai_gpt-5.1-codex.js | 31 ++-- .../outputs/openrouter_sherlock-dash-alpha.js | 16 -- .../openrouter_sherlock-think-alpha.js | 37 ++--- .../anthropic_claude-sonnet-4.5 TEMP_0.7.js | 7 +- tests/3_lis/outputs/google_gemini-2.5-pro.js | 14 +- .../outputs/google_gemini-3-pro-preview.js | 7 + .../outputs/moonshotai_kimi-k2-thinking.js | 17 ++- tests/3_lis/outputs/openai_gpt-5.1-chat.js | 10 -- tests/3_lis/outputs/openai_gpt-5.1-codex.js | 14 +- .../outputs/openrouter_sherlock-dash-alpha.js | 12 -- .../openrouter_sherlock-think-alpha.js | 14 +- .../outputs/google_gemini-2.5-pro.js | 2 +- .../outputs/google_gemini-3-pro-preview.js | 5 + .../outputs/moonshotai_kimi-k2-thinking.js | 15 +- .../outputs/openai_gpt-5.1-chat.js | 5 - .../outputs/openai_gpt-5.1-codex.js | 4 +- .../outputs/openrouter_sherlock-dash-alpha.js | 5 - .../openrouter_sherlock-think-alpha.js | 5 +- .../anthropic_claude-sonnet-4.5 TEMP_0.7.js | 2 +- .../outputs/google_gemini-2.5-pro.js | 14 +- .../outputs/google_gemini-3-pro-preview.js | 5 + .../outputs/moonshotai_kimi-k2-thinking.js | 16 +- .../outputs/openai_gpt-5.1-chat.js | 5 - .../outputs/openai_gpt-5.1-codex.js | 8 +- .../outputs/openrouter_sherlock-dash-alpha.js | 35 ----- .../openrouter_sherlock-think-alpha.js | 6 +- .../anthropic_claude-sonnet-4.5 TEMP_0.7.js | 14 +- .../outputs/google_gemini-2.5-pro.js | 63 ++++---- .../outputs/google_gemini-3-pro-preview.js | 22 +++ .../outputs/moonshotai_kimi-k2-thinking.js | 16 +- .../outputs/openai_gpt-5.1-chat.js | 22 --- .../outputs/openai_gpt-5.1-codex.js | 30 ++-- .../outputs/openrouter_sherlock-dash-alpha.js | 2 - .../openrouter_sherlock-think-alpha.js | 42 +++--- .../anthropic_claude-sonnet-4.5 TEMP_0.7.js | 94 ++++++------ .../outputs/google_gemini-2.5-pro.js | 98 ++++++------ .../outputs/google_gemini-3-pro-preview.js | 48 ++++++ .../outputs/moonshotai_kimi-k2-thinking.js | 74 +++++---- .../outputs/openai_gpt-5.1-chat.js | 38 ----- .../outputs/openai_gpt-5.1-codex.js | 90 +++++------ .../outputs/openrouter_sherlock-dash-alpha.js | 67 --------- .../openrouter_sherlock-think-alpha.js | 124 ++++++++------- .../anthropic_claude-sonnet-4.5 TEMP_0.7.js | 9 +- .../outputs/google_gemini-2.5-pro.js | 25 ++-- .../outputs/google_gemini-3-pro-preview.js | 14 ++ .../outputs/moonshotai_kimi-k2-thinking.js | 36 +++-- .../outputs/openai_gpt-5.1-chat.js | 8 - .../outputs/openai_gpt-5.1-codex.js | 14 +- .../outputs/openrouter_sherlock-dash-alpha.js | 13 -- .../openrouter_sherlock-think-alpha.js | 29 ++-- .../anthropic_claude-sonnet-4.5 TEMP_0.7.js | 7 +- .../outputs/google_gemini-2.5-pro.js | 26 +--- .../outputs/google_gemini-3-pro-preview.js | 32 ++++ .../outputs/moonshotai_kimi-k2-thinking.js | 73 ++++++++- .../outputs/openai_gpt-5.1-chat.js | 23 --- .../outputs/openai_gpt-5.1-codex.js | 33 ++-- .../outputs/openrouter_sherlock-dash-alpha.js | 26 ---- .../openrouter_sherlock-think-alpha.js | 29 ++-- 84 files changed, 1086 insertions(+), 1088 deletions(-) create mode 100644 tests/10_scrypt_hash/outputs/anthropic_claude-sonnet-4.5 TEMP_0.7.js create mode 100644 tests/10_scrypt_hash/outputs/google_gemini-2.5-pro.js create mode 100644 tests/10_scrypt_hash/outputs/google_gemini-3-pro-preview.js create mode 100644 tests/10_scrypt_hash/outputs/moonshotai_kimi-k2-thinking.js create mode 100644 tests/10_scrypt_hash/outputs/openai_gpt-5.1-codex.js create mode 100644 tests/10_scrypt_hash/outputs/openrouter_sherlock-think-alpha.js create mode 100644 tests/11_geospatial/outputs/anthropic_claude-sonnet-4.5 TEMP_0.7.js create mode 100644 tests/11_geospatial/outputs/google_gemini-2.5-pro.js create mode 100644 tests/11_geospatial/outputs/google_gemini-3-pro-preview.js create mode 100644 tests/11_geospatial/outputs/moonshotai_kimi-k2-thinking.js create mode 100644 tests/11_geospatial/outputs/openai_gpt-5.1-codex.js create mode 100644 tests/11_geospatial/outputs/openrouter_sherlock-think-alpha.js create mode 100644 tests/1_dijkstra/outputs/google_gemini-3-pro-preview.js delete mode 100644 tests/1_dijkstra/outputs/openai_gpt-5.1-chat.js delete mode 100644 tests/1_dijkstra/outputs/openrouter_sherlock-dash-alpha.js create mode 100644 tests/2_convex_hull/outputs/google_gemini-3-pro-preview.js delete mode 100644 tests/2_convex_hull/outputs/openai_gpt-5.1-chat.js delete mode 100644 tests/2_convex_hull/outputs/openrouter_sherlock-dash-alpha.js create mode 100644 tests/3_lis/outputs/google_gemini-3-pro-preview.js delete mode 100644 tests/3_lis/outputs/openai_gpt-5.1-chat.js delete mode 100644 tests/3_lis/outputs/openrouter_sherlock-dash-alpha.js create mode 100644 tests/4_determinant/outputs/google_gemini-3-pro-preview.js delete mode 100644 tests/4_determinant/outputs/openai_gpt-5.1-chat.js delete mode 100644 tests/4_determinant/outputs/openrouter_sherlock-dash-alpha.js create mode 100644 tests/5_markdown_parser/outputs/google_gemini-3-pro-preview.js delete mode 100644 tests/5_markdown_parser/outputs/openai_gpt-5.1-chat.js delete mode 100644 tests/5_markdown_parser/outputs/openrouter_sherlock-dash-alpha.js create mode 100644 tests/6_csv_processor/outputs/google_gemini-3-pro-preview.js delete mode 100644 tests/6_csv_processor/outputs/openai_gpt-5.1-chat.js delete mode 100644 tests/6_csv_processor/outputs/openrouter_sherlock-dash-alpha.js create mode 100644 tests/7_scheduler/outputs/google_gemini-3-pro-preview.js delete mode 100644 tests/7_scheduler/outputs/openai_gpt-5.1-chat.js delete mode 100644 tests/7_scheduler/outputs/openrouter_sherlock-dash-alpha.js create mode 100644 tests/8_json_validator/outputs/google_gemini-3-pro-preview.js delete mode 100644 tests/8_json_validator/outputs/openai_gpt-5.1-chat.js delete mode 100644 tests/8_json_validator/outputs/openrouter_sherlock-dash-alpha.js create mode 100644 tests/9_stream_visualizer/outputs/google_gemini-3-pro-preview.js delete mode 100644 tests/9_stream_visualizer/outputs/openai_gpt-5.1-chat.js delete mode 100644 tests/9_stream_visualizer/outputs/openrouter_sherlock-dash-alpha.js diff --git a/results.json b/results.json index c05eb45..5dfd95f 100644 --- a/results.json +++ b/results.json @@ -1,79 +1,80 @@ { - "openai/gpt-5.1-codex": { - "1_dijkstra": 15.241279893, - "2_convex_hull": 13.933983282, - "3_lis": 3.980165064000001, - "4_determinant": 6.332550646999996, - "5_markdown_parser": 3.2380716380000014, - "6_csv_processor": 26.09038364200001, - "7_scheduler": 130.18603798900003, - "8_json_validator": 8.38715121099999, - "9_stream_visualizer": 12.031535295999987 - }, - "openai/gpt-5.1-chat": { - "1_dijkstra": 2.65463601799999, - "2_convex_hull": 3.1764218759999787, - "3_lis": 2.5808361240000233, - "4_determinant": 1.857067280999996, - "5_markdown_parser": 2.1500550130000047, - "6_csv_processor": 2.8134082990000024, - "7_scheduler": 6.116577822999999, - "8_json_validator": 1.477971265, - "9_stream_visualizer": 1.7076946140000073 - }, - "google/gemini-2.5-pro": { - "1_dijkstra": 33.989065073000006, - "2_convex_hull": 56.566219838000016, - "3_lis": 52.14045403000002, - "4_determinant": 14.913826469999972, - "5_markdown_parser": 26.86344819299999, - "6_csv_processor": 49.397067434999975, - "7_scheduler": 52.55558026300004, - "8_json_validator": 19.59284627099999, - "9_stream_visualizer": 36.41860035799991 + "google/gemini-3-pro-preview": { + "10_scrypt_hash": 39.295109482, + "11_geospatial": 38.59770959899999, + "1_dijkstra": 34.202315816, + "2_convex_hull": 34.06182440299999, + "3_lis": 25.023427584999997, + "4_determinant": 28.093709440000005, + "5_markdown_parser": 28.463938538000015, + "6_csv_processor": 38.290726488999994, + "7_scheduler": 67.523956824, + "8_json_validator": 16.506907749000007, + "9_stream_visualizer": 51.923362084000026 }, "anthropic/claude-sonnet-4.5 TEMP:0.7": { - "1_dijkstra": 4.49742717099993, - "2_convex_hull": 4.570548665000009, - "3_lis": 2.375867489000084, - "4_determinant": 1.5574152070001, - "5_markdown_parser": 1.8310976730000694, - "6_csv_processor": 4.079893573999987, - "7_scheduler": 12.446870330999955, - "8_json_validator": 2.8953664760000537, - "9_stream_visualizer": 5.022439357000054 + "10_scrypt_hash": 2.994402775000024, + "11_geospatial": 3.173007857000048, + "1_dijkstra": 4.721320241999987, + "2_convex_hull": 4.782739678999991, + "3_lis": 2.566319416000042, + "4_determinant": 2.087922611000016, + "5_markdown_parser": 2.1563547050000054, + "6_csv_processor": 4.368516923999996, + "7_scheduler": 10.690530350000016, + "8_json_validator": 2.9041606949999696, + "9_stream_visualizer": 4.411488517000049 + }, + "openai/gpt-5.1-codex": { + "10_scrypt_hash": 19.945625629000016, + "11_geospatial": 7.752952860000019, + "1_dijkstra": 18.825615109000005, + "2_convex_hull": 24.519327066999978, + "3_lis": 13.449256432000023, + "4_determinant": 3.5313777560000306, + "5_markdown_parser": 4.871686004000018, + "6_csv_processor": 31.731031262999984, + "7_scheduler": 91.32724592999998, + "8_json_validator": 11.784968072999968, + "9_stream_visualizer": 17.32446443499997 }, "moonshotai/kimi-k2-thinking": { - "1_dijkstra": 34.72660079400001, - "2_convex_hull": 42.421906253, - "3_lis": 52.291474074000014, - "4_determinant": 37.432558806, - "5_markdown_parser": 35.437114885999996, - "6_csv_processor": 91.85763109999999, - "7_scheduler": 184.65146969499997, - "8_json_validator": 81.96185510699998, - "9_stream_visualizer": 31.27018206100003 + "10_scrypt_hash": 54.48318050600006, + "11_geospatial": 123.94316572699998, + "1_dijkstra": 20.75571812199999, + "2_convex_hull": 281.26114928399994, + "3_lis": 78.25152572599984, + "4_determinant": 67.81623509099987, + "5_markdown_parser": 154.2897356459999, + "6_csv_processor": 85.1170599280002, + "7_scheduler": 389.4384002489999, + "8_json_validator": 17.501368902000134, + "9_stream_visualizer": 98.03424570999994 + }, + "google/gemini-2.5-pro": { + "10_scrypt_hash": 33.5175050580001, + "11_geospatial": 31.009794073000318, + "1_dijkstra": 45.908529550999866, + "2_convex_hull": 85.32745476700039, + "3_lis": 32.75355649500014, + "4_determinant": 27.239392394999975, + "5_markdown_parser": 27.228569728999865, + "6_csv_processor": 69.48256337699992, + "7_scheduler": 54.015430929000026, + "8_json_validator": 29.125379850999916, + "9_stream_visualizer": 36.110917992000005 }, "openrouter/sherlock-think-alpha": { - "1_dijkstra": 34.012272204, - "2_convex_hull": 47.377176928, - "3_lis": 18.49963934400001, - "4_determinant": 20.327296623999995, - "5_markdown_parser": 34.069916891999995, - "6_csv_processor": 19.902450771000005, - "7_scheduler": 82.133111714, - "8_json_validator": 31.42142794699996, - "9_stream_visualizer": 35.74114956699999 - }, - "openrouter/sherlock-dash-alpha": { - "1_dijkstra": 2.7058817040000003, - "2_convex_hull": 3.9343546879999995, - "3_lis": 1.2894778209999995, - "4_determinant": 0.611742537, - "5_markdown_parser": 4.020213965999999, - "6_csv_processor": 3.107556931000001, - "7_scheduler": 7.806581231, - "8_json_validator": 1.4850442509999993, - "9_stream_visualizer": 2.5679872179999985 + "10_scrypt_hash": 9.486372194000054, + "11_geospatial": 15.555460506999864, + "1_dijkstra": 21.514197755000087, + "2_convex_hull": 35.37556943300041, + "3_lis": 17.00031832400011, + "4_determinant": 8.939955472999719, + "5_markdown_parser": 15.81524256400019, + "6_csv_processor": 23.44287434099987, + "7_scheduler": 68.04158863600017, + "8_json_validator": 19.484740249000023, + "9_stream_visualizer": 28.426358369000255 } } \ No newline at end of file diff --git a/tests/10_scrypt_hash/outputs/anthropic_claude-sonnet-4.5 TEMP_0.7.js b/tests/10_scrypt_hash/outputs/anthropic_claude-sonnet-4.5 TEMP_0.7.js new file mode 100644 index 0000000..78fd104 --- /dev/null +++ b/tests/10_scrypt_hash/outputs/anthropic_claude-sonnet-4.5 TEMP_0.7.js @@ -0,0 +1,14 @@ +async function hashPassword(password, salt) { + const { scrypt } = await import('https://cdn.jsdelivr.net/npm/scrypt-js@3.0.1/+esm'); + const enc = new TextEncoder(); + const hash = await scrypt( + enc.encode(password), + enc.encode(salt), + 1024, + 8, + 1, + 32 + ); + return Array.from(hash, b => b.toString(16).padStart(2, '0')).join(''); +} +export default hashPassword; \ No newline at end of file diff --git a/tests/10_scrypt_hash/outputs/google_gemini-2.5-pro.js b/tests/10_scrypt_hash/outputs/google_gemini-2.5-pro.js new file mode 100644 index 0000000..0101308 --- /dev/null +++ b/tests/10_scrypt_hash/outputs/google_gemini-2.5-pro.js @@ -0,0 +1,19 @@ +const hashPassword = async (password, salt) => { + const { default: scrypt } = await import('https://cdn.jsdelivr.net/npm/scrypt-js@3.0.1/scrypt.min.js'); + + const encoder = new TextEncoder(); + + const hashBytes = await scrypt( + encoder.encode(password), + encoder.encode(salt), + 1024, + 8, + 1, + 32 + ); + + return [...hashBytes] + .map(byte => byte.toString(16).padStart(2, '0')) + .join(''); +}; +export default hashPassword; \ No newline at end of file diff --git a/tests/10_scrypt_hash/outputs/google_gemini-3-pro-preview.js b/tests/10_scrypt_hash/outputs/google_gemini-3-pro-preview.js new file mode 100644 index 0000000..0cb2d2f --- /dev/null +++ b/tests/10_scrypt_hash/outputs/google_gemini-3-pro-preview.js @@ -0,0 +1,7 @@ +const hashPassword = async (pwd, salt) => { + const { scrypt } = await import('https://unpkg.com/scrypt-js@3.0.1/scrypt.js') + const e = new TextEncoder() + const h = await scrypt(e.encode(pwd), e.encode(salt), 1024, 8, 1, 32) + return Array.from(h, b => b.toString(16).padStart(2, '0')).join('') +} +export default hashPassword; \ No newline at end of file diff --git a/tests/10_scrypt_hash/outputs/moonshotai_kimi-k2-thinking.js b/tests/10_scrypt_hash/outputs/moonshotai_kimi-k2-thinking.js new file mode 100644 index 0000000..a36208b --- /dev/null +++ b/tests/10_scrypt_hash/outputs/moonshotai_kimi-k2-thinking.js @@ -0,0 +1,7 @@ +async function hashPassword(password, salt) { + const { scrypt } = await import('https://cdn.jsdelivr.net/npm/scrypt-js@3.0.1/+esm'); + const e = new TextEncoder(); + const hash = await scrypt(e.encode(password), e.encode(salt), 1024, 8, 1, 32); + return Array.from(hash, b => b.toString(16).padStart(2, '0')).join(''); +} +export default hashPassword; \ No newline at end of file diff --git a/tests/10_scrypt_hash/outputs/openai_gpt-5.1-codex.js b/tests/10_scrypt_hash/outputs/openai_gpt-5.1-codex.js new file mode 100644 index 0000000..8ccafba --- /dev/null +++ b/tests/10_scrypt_hash/outputs/openai_gpt-5.1-codex.js @@ -0,0 +1,9 @@ +const enc = new TextEncoder; +let scryptLoader; +const hashPassword = async (password, salt) => { + scryptLoader ||= import('https://cdn.jsdelivr.net/npm/scrypt-js@3.0.1/+esm').then(({ scrypt }) => scrypt); + const scrypt = await scryptLoader; + const hash = await scrypt(enc.encode(password), enc.encode(salt), 1024, 8, 1, 32); + return [...hash].map(v => v.toString(16).padStart(2, '0')).join(''); +}; +export default hashPassword; \ No newline at end of file diff --git a/tests/10_scrypt_hash/outputs/openrouter_sherlock-think-alpha.js b/tests/10_scrypt_hash/outputs/openrouter_sherlock-think-alpha.js new file mode 100644 index 0000000..96ed13a --- /dev/null +++ b/tests/10_scrypt_hash/outputs/openrouter_sherlock-think-alpha.js @@ -0,0 +1,2 @@ +async function hashPassword(password,salt){const{scrypt}=await import('https://cdn.skypack.dev/scrypt-js');const e=new TextEncoder();const h=await scrypt(e.encode(password),e.encode(salt),1024,8,1,32);return Array.from(h).map(b=>b.toString(16).padStart(2,'0')).join('')} +export default hashPassword; \ No newline at end of file diff --git a/tests/11_geospatial/outputs/anthropic_claude-sonnet-4.5 TEMP_0.7.js b/tests/11_geospatial/outputs/anthropic_claude-sonnet-4.5 TEMP_0.7.js new file mode 100644 index 0000000..c3d5200 --- /dev/null +++ b/tests/11_geospatial/outputs/anthropic_claude-sonnet-4.5 TEMP_0.7.js @@ -0,0 +1,14 @@ +const analyzeGPS = async (readings, boundary) => { + const turf = await import('https://esm.sh/@turf/turf@7.1.0'); + + const validReadings = readings + .filter(r => turf.booleanPointInPolygon(turf.point(r.loc), boundary)) + .sort((a, b) => a.ts - b.ts); + + if (validReadings.length < 2) return 0; + + const lineString = turf.lineString(validReadings.map(r => r.loc)); + + return Math.round(turf.length(lineString) * 100) / 100; +}; +export default analyzeGPS; \ No newline at end of file diff --git a/tests/11_geospatial/outputs/google_gemini-2.5-pro.js b/tests/11_geospatial/outputs/google_gemini-2.5-pro.js new file mode 100644 index 0000000..3bb99bf --- /dev/null +++ b/tests/11_geospatial/outputs/google_gemini-2.5-pro.js @@ -0,0 +1,18 @@ +const analyzeGPS = async (readings, boundary) => { + const t = await import('https://cdn.jsdelivr.net/npm/@turf/turf'); + + const sortedLocations = readings + .filter(r => t.booleanPointInPolygon(r.loc, boundary, { ignoreBoundary: true })) + .sort((a, b) => a.ts - b.ts) + .map(r => r.loc); + + if (sortedLocations.length < 2) { + return 0; + } + + const path = t.lineString(sortedLocations); + const length = t.length(path, { units: 'kilometers' }); + + return Math.round(length * 100) / 100; +}; +export default analyzeGPS; \ No newline at end of file diff --git a/tests/11_geospatial/outputs/google_gemini-3-pro-preview.js b/tests/11_geospatial/outputs/google_gemini-3-pro-preview.js new file mode 100644 index 0000000..236d41c --- /dev/null +++ b/tests/11_geospatial/outputs/google_gemini-3-pro-preview.js @@ -0,0 +1,13 @@ +const analyzeGPS = async (readings, boundary) => { + const { point, booleanPointInPolygon, lineString, length } = await import('https://esm.sh/@turf/turf'); + + const path = readings + .filter(({ loc }) => booleanPointInPolygon(point(loc), boundary, { ignoreBoundary: true })) + .sort((a, b) => a.ts - b.ts) + .map(({ loc }) => loc); + + return path.length < 2 + ? 0 + : +length(lineString(path), { units: 'kilometers' }).toFixed(2); +}; +export default analyzeGPS; \ No newline at end of file diff --git a/tests/11_geospatial/outputs/moonshotai_kimi-k2-thinking.js b/tests/11_geospatial/outputs/moonshotai_kimi-k2-thinking.js new file mode 100644 index 0000000..edd1491 --- /dev/null +++ b/tests/11_geospatial/outputs/moonshotai_kimi-k2-thinking.js @@ -0,0 +1,12 @@ +async function analyzeGPS(readings, boundary) { + try { + if (!Array.isArray(readings) || !boundary) return 0; + const turf = await import('https://cdn.skypack.dev/@turf/turf'), + v = readings.filter(r => r?.loc && turf.booleanPointInPolygon(r.loc, boundary, {ignoreBoundary: true})) + .sort((a, b) => a.ts - b.ts); + return v.length < 2 ? 0 : Math.round(turf.length(turf.lineString(v.map(r => r.loc)), {units: 'kilometers'}) * 100) / 100; + } catch { + return 0; + } +} +export default analyzeGPS; \ No newline at end of file diff --git a/tests/11_geospatial/outputs/openai_gpt-5.1-codex.js b/tests/11_geospatial/outputs/openai_gpt-5.1-codex.js new file mode 100644 index 0000000..aa94eeb --- /dev/null +++ b/tests/11_geospatial/outputs/openai_gpt-5.1-codex.js @@ -0,0 +1,8 @@ +async function analyzeGPS(readings,boundary){ +const{booleanPointInPolygon,lineString,length}=await import('https://cdn.jsdelivr.net/npm/@turf/turf@6.5.0/dist/turf.esm.min.js'); +const pts=readings.filter(r=>booleanPointInPolygon({type:'Point',coordinates:r.loc},boundary,{ignoreBoundary:true})).sort((a,b)=>a.ts-b.ts); +if(pts.length<2)return 0; +const km=length(lineString(pts.map(r=>r.loc)),{units:'kilometers'}); +return Math.round(km*100)/100; +} +export default analyzeGPS; \ No newline at end of file diff --git a/tests/11_geospatial/outputs/openrouter_sherlock-think-alpha.js b/tests/11_geospatial/outputs/openrouter_sherlock-think-alpha.js new file mode 100644 index 0000000..9b83486 --- /dev/null +++ b/tests/11_geospatial/outputs/openrouter_sherlock-think-alpha.js @@ -0,0 +1,8 @@ +async function analyzeGPS(readings,boundary){ + const{turf}=await import('https://cdn.skypack.dev/@turf/turf'); + const valid=readings + .filter(({loc})=>turf.booleanPointInPolygon([loc[0],loc[1]],boundary,{ignoreBoundary:true})) + .sort((a,b)=>a.ts-b.ts); + return valid.length<2?0:+turf.length(turf.lineString(valid.map(({loc})=>loc)),{units:'kilometers'}).toFixed(2); +} +export default analyzeGPS; \ No newline at end of file diff --git a/tests/1_dijkstra/outputs/anthropic_claude-sonnet-4.5 TEMP_0.7.js b/tests/1_dijkstra/outputs/anthropic_claude-sonnet-4.5 TEMP_0.7.js index b0feb33..1f6b2ea 100644 --- a/tests/1_dijkstra/outputs/anthropic_claude-sonnet-4.5 TEMP_0.7.js +++ b/tests/1_dijkstra/outputs/anthropic_claude-sonnet-4.5 TEMP_0.7.js @@ -1,24 +1,27 @@ async function findShortestPath(graph, start, end) { - const { default: PriorityQueue } = await import('https://cdn.jsdelivr.net/npm/js-priority-queue@0.1.5/+esm'); - - const distances = Object.keys(graph).reduce((acc, node) => ({ ...acc, [node]: Infinity }), {}); - distances[start] = 0; + const { default: PriorityQueue } = await import('https://cdn.skypack.dev/js-priority-queue'); + const distances = {}; + const visited = new Set(); const pq = new PriorityQueue({ comparator: (a, b) => a.dist - b.dist }); + + for (const node in graph) distances[node] = Infinity; + distances[start] = 0; pq.queue({ node: start, dist: 0 }); - const visited = new Set(); - - while (pq.length > 0) { + while (pq.length) { const { node, dist } = pq.dequeue(); if (visited.has(node)) continue; - visited.add(node); - if (node === end) return dist; - for (const [neighbor, weight] of Object.entries(graph[node] || {})) { - const newDist = dist + weight; + visited.add(node); + + for (const neighbor in graph[node]) { + if (visited.has(neighbor)) continue; + + const newDist = dist + graph[node][neighbor]; + if (newDist < distances[neighbor]) { distances[neighbor] = newDist; pq.queue({ node: neighbor, dist: newDist }); @@ -26,6 +29,6 @@ async function findShortestPath(graph, start, end) { } } - return distances[end]; + return Infinity; } export default findShortestPath; \ No newline at end of file diff --git a/tests/1_dijkstra/outputs/google_gemini-2.5-pro.js b/tests/1_dijkstra/outputs/google_gemini-2.5-pro.js index fa539e2..c52f715 100644 --- a/tests/1_dijkstra/outputs/google_gemini-2.5-pro.js +++ b/tests/1_dijkstra/outputs/google_gemini-2.5-pro.js @@ -1,36 +1,34 @@ -const findShortestPath = async (graph, startNode, endNode) => { +const findShortestPath = async (graph, start, end) => { const { default: PriorityQueue } = await import('https://cdn.jsdelivr.net/npm/js-priority-queue@0.1.5/priority-queue.min.js'); - const distances = Object.fromEntries( - Object.keys(graph).map(node => [node, 1 / 0]) + const dists = Object.fromEntries( + Object.keys(graph).map(node => [node, Infinity]) ); - distances[startNode] = 0; - const pq = new PriorityQueue({ - comparator: (a, b) => a.priority - b.priority - }); - pq.queue({ node: startNode, priority: 0 }); + const pq = new PriorityQueue({ comparator: (a, b) => a.priority - b.priority }); + + dists[start] = 0; + pq.queue({ node: start, priority: 0 }); while (pq.length) { - const { node: u, priority: dist } = pq.dequeue(); + const { node: u, priority: currentDist } = pq.dequeue(); - if (dist > distances[u]) { + if (currentDist > dists[u]) { continue; } - if (u === endNode) { - break; - } + if (u === end) break; - for (const [v, weight] of Object.entries(graph[u] ?? {})) { - const newDist = distances[u] + weight; - if (newDist < distances[v]) { - distances[v] = newDist; - pq.queue({ node: v, priority: newDist }); + for (const [v, weight] of Object.entries(graph[u])) { + const distThroughU = dists[u] + weight; + + if (distThroughU < dists[v]) { + dists[v] = distThroughU; + pq.queue({ node: v, priority: distThroughU }); } } } - return distances[endNode]; + return dists[end]; }; export default findShortestPath; \ No newline at end of file diff --git a/tests/1_dijkstra/outputs/google_gemini-3-pro-preview.js b/tests/1_dijkstra/outputs/google_gemini-3-pro-preview.js new file mode 100644 index 0000000..6bcff19 --- /dev/null +++ b/tests/1_dijkstra/outputs/google_gemini-3-pro-preview.js @@ -0,0 +1,19 @@ +const findShortestPath = async (g, s, e) => { + const { default: P } = await import('https://cdn.skypack.dev/js-priority-queue') + const d = { [s]: 0 }, q = new P({ comparator: (a, b) => a.w - b.w }) + q.queue({ w: 0, n: s }) + while (q.length) { + const { w, n } = q.dequeue() + if (n === e) return w + if (w > (d[n] ?? 1 / 0)) continue + for (const v in g[n]) { + const t = w + g[n][v] + if (t < (d[v] ?? 1 / 0)) { + d[v] = t + q.queue({ w: t, n: v }) + } + } + } + return 1 / 0 +} +export default findShortestPath; \ No newline at end of file diff --git a/tests/1_dijkstra/outputs/moonshotai_kimi-k2-thinking.js b/tests/1_dijkstra/outputs/moonshotai_kimi-k2-thinking.js index 5746577..1b3529a 100644 --- a/tests/1_dijkstra/outputs/moonshotai_kimi-k2-thinking.js +++ b/tests/1_dijkstra/outputs/moonshotai_kimi-k2-thinking.js @@ -1,35 +1,24 @@ async function findShortestPath(graph, start, end) { - let PriorityQueue; - try { - const mod = await import('https://esm.sh/js-priority-queue@1.0.0'); - PriorityQueue = mod.default || mod; - } catch { - throw new Error('Failed to load priority queue library'); - } - - if (!(start in graph) || !(end in graph)) return Infinity; - if (start === end) return 0; - - const dist = { [start]: 0 }; - const pq = new PriorityQueue({ - comparator: (a, b) => a[1] - b[1], - initialValues: [[start, 0]] - }); + const { default: Q } = await import('https://cdn.jsdelivr.net/npm/js-priority-queue@0.1.5/index.min.js'); + const dist = { [start]: 0 }, visited = new Set(); + const pq = new Q({ comparator: (a, b) => dist[a] - dist[b] }); + pq.queue(start); while (pq.length) { - const [node, d] = pq.dequeue(); - if (node === end) return d; - if (d > (dist[node] ?? Infinity)) continue; - - for (const [neighbor, weight] of Object.entries(graph[node])) { - const newDist = d + weight; - if (newDist < (dist[neighbor] ?? Infinity)) { - dist[neighbor] = newDist; - pq.queue([neighbor, newDist]); + const node = pq.dequeue(); + if (node === end) return dist[end]; + if (visited.has(node)) continue; + visited.add(node); + const nodeDist = dist[node]; + for (const [adj, weight] of Object.entries(graph[node] || {})) { + if (visited.has(adj)) continue; + const newDist = nodeDist + weight; + if (newDist < (dist[adj] ?? Infinity)) { + dist[adj] = newDist; + pq.queue(adj); } } } - return Infinity; } export default findShortestPath; \ No newline at end of file diff --git a/tests/1_dijkstra/outputs/openai_gpt-5.1-chat.js b/tests/1_dijkstra/outputs/openai_gpt-5.1-chat.js deleted file mode 100644 index 1280658..0000000 --- a/tests/1_dijkstra/outputs/openai_gpt-5.1-chat.js +++ /dev/null @@ -1,23 +0,0 @@ -async function findShortestPath(g,s,e){ - const {default:Q}=await import('https://cdn.jsdelivr.net/npm/js-priority-queue@latest/dist/priority-queue.min.js') - const d={},v={} - for(const k in g)d[k]=Infinity - d[s]=0 - const q=new Q({comparator:(a,b)=>a[1]-b[1]}) - q.queue([s,0]) - while(q.length){ - const [n,w]=q.dequeue() - if(v[n])continue - v[n]=1 - if(n===e)return w - for(const k in g[n]){ - const nw=w+g[n][k] - if(nw{ - if(s===t)return 0 - const{default:PriorityQueue}=await import('https://cdn.skypack.dev/js-priority-queue') - if(!g[s]||!g[t])return Infinity - const seen=new Map([[s,0]]) - const pq=new PriorityQueue({comparator:(a,b)=>a[1]-b[1]}) - pq.queue([s,0]) +const src='https://esm.sh/js-priority-queue@1' +let load +const getPQ=()=>load||(load=import(src).then(m=>m.default)) +const findShortestPath=async(g,s,e)=>{ + const PQ=await getPQ() + const pq=new PQ({comparator:(a,b)=>a[0]-b[0]}) + const dist=new Map([[s,0]]) + const done=new Set + pq.queue([0,s]) while(pq.length){ - const[n,d]=pq.dequeue() - if(d>(seen.get(n)??Infinity))continue - if(n===t)return d - const nbrs=g[n]||{} - for(const k in nbrs){ - const nd=d+nbrs[k] - if(nd<(seen.get(k)??Infinity)){ - seen.set(k,nd) - pq.queue([k,nd]) + const [d,n]=pq.dequeue() + if(done.has(n))continue + done.add(n) + if(n===e)return d + const edges=g[n] + if(!edges)continue + for(const k in edges){ + const w=d+edges[k] + if(w<(dist.get(k)??Infinity)){ + dist.set(k,w) + pq.queue([w,k]) } } } diff --git a/tests/1_dijkstra/outputs/openrouter_sherlock-dash-alpha.js b/tests/1_dijkstra/outputs/openrouter_sherlock-dash-alpha.js deleted file mode 100644 index 8380d82..0000000 --- a/tests/1_dijkstra/outputs/openrouter_sherlock-dash-alpha.js +++ /dev/null @@ -1,20 +0,0 @@ -async function findShortestPath(graph, start, end) { - const { PriorityQueue } = await import('https://cdn.skypack.dev/js-priority-queue'); - const pq = new PriorityQueue({ comparator: (a, b) => a[1] - b[1] }); - const dist = {}; Object.keys(graph).forEach(n => dist[n] = Infinity); dist[start] = 0; - pq.queue([start, 0]); - while (!pq.isEmpty()) { - const [u, d] = pq.dequeue(); - if (u === end) return d; - if (d > dist[u]) continue; - for (const [v, w] of Object.entries(graph[u] || {})) { - const nd = d + w; - if (nd < dist[v]) { - dist[v] = nd; - pq.queue([v, nd]); - } - } - } - return Infinity; -} -export default findShortestPath; \ No newline at end of file diff --git a/tests/1_dijkstra/outputs/openrouter_sherlock-think-alpha.js b/tests/1_dijkstra/outputs/openrouter_sherlock-think-alpha.js index e029a30..aa57ba4 100644 --- a/tests/1_dijkstra/outputs/openrouter_sherlock-think-alpha.js +++ b/tests/1_dijkstra/outputs/openrouter_sherlock-think-alpha.js @@ -1,19 +1,20 @@ async function findShortestPath(graph,start,end){ - const{PriorityQueue}=await import('https://cdn.skypack.dev/js-priority-queue'); + const{default:PriorityQueue}=await import('https://cdn.skypack.dev/js-priority-queue'); const dist={}; - for(let n in graph)dist[n]=Infinity; + const pq=new PriorityQueue({comparator:(x,y)=>x.d-y.d}); + for(const n of Object.keys(graph))dist[n]=Infinity; dist[start]=0; - const pq=new PriorityQueue({comparator:(a,b)=>a.d-b.d}); - pq.queue({node:start,d:0}); + pq.queue({n:start,d:0}); while(!pq.isEmpty()){ - const{node,d}=pq.dequeue(); - if(d>dist[node])continue; - if(node===end)return d; - for(let nei in graph[node]){ - const alt=d+graph[node][nei]; + const{n:n,d:d}=pq.dequeue(); + if(d>dist[n])continue; + if(n===end)return d; + for(let nei in graph[n]){ + const w=graph[n][nei]; + const alt=d+w; if(alt (a.x - o.x) * (b.y - o.y) - (a.y - o.y) * (b.x - o.x); - const buildHull = pts => { + const buildHull = (pts) => { const hull = []; for (const p of pts) { while (hull.length >= 2 && cross(hull[hull.length - 2], hull[hull.length - 1], p) <= 0) { diff --git a/tests/2_convex_hull/outputs/google_gemini-2.5-pro.js b/tests/2_convex_hull/outputs/google_gemini-2.5-pro.js index 2271a65..9a7fc98 100644 --- a/tests/2_convex_hull/outputs/google_gemini-2.5-pro.js +++ b/tests/2_convex_hull/outputs/google_gemini-2.5-pro.js @@ -1,29 +1,27 @@ const findConvexHull = async (points) => { - const { sortBy, uniqWith, isEqual } = - await import('https://cdn.jsdelivr.net/npm/lodash-es@4.17.21/lodash.js'); + const _ = await import('https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js'); - const cross = (o, a, b) => (a.x - o.x) * (b.y - o.y) - (a.y - o.y) * (b.x - o.x); - - const pts = sortBy(uniqWith(points, isEqual), ['x', 'y']); - - if (pts.length < 3) return pts; - - const lower = []; - for (const p of pts) { - while (lower.length >= 2 && cross(lower.at(-2), lower.at(-1), p) <= 0) { - lower.pop(); - } - lower.push(p); + const uniquePts = _.uniqWith(points, _.isEqual); + if (uniquePts.length < 3) { + return uniquePts; } - const upper = []; - for (let i = pts.length - 1; i >= 0; i--) { - const p = pts[i]; - while (upper.length >= 2 && cross(upper.at(-2), upper.at(-1), p) <= 0) { - upper.pop(); - } - upper.push(p); - } + const crossProduct = (o, a, b) => + (a.x - o.x) * (b.y - o.y) - (a.y - o.y) * (b.x - o.x); + + const sortedPts = _.sortBy(uniquePts, ['x', 'y']); + + const buildHalfHull = (pts) => + pts.reduce((hull, p) => { + while (hull.length >= 2 && crossProduct(hull.at(-2), hull.at(-1), p) <= 0) { + hull.pop(); + } + hull.push(p); + return hull; + }, []); + + const lower = buildHalfHull(sortedPts); + const upper = buildHalfHull([...sortedPts].reverse()); return [...lower.slice(0, -1), ...upper.slice(0, -1)]; }; diff --git a/tests/2_convex_hull/outputs/google_gemini-3-pro-preview.js b/tests/2_convex_hull/outputs/google_gemini-3-pro-preview.js new file mode 100644 index 0000000..d01d8e1 --- /dev/null +++ b/tests/2_convex_hull/outputs/google_gemini-3-pro-preview.js @@ -0,0 +1,22 @@ +const findConvexHull = async (pts) => { + const { default: _ } = await import('https://cdn.skypack.dev/lodash'); + + const P = _.sortBy(_.uniqWith(pts, _.isEqual), ['x', 'y']); + const n = P.length, k = [], C = (a, b, c) => (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x); + + if (n < 3) return P; + + for (let i = 0; i < n; i++) { + while (k.length >= 2 && C(k[k.length - 2], k[k.length - 1], P[i]) <= 0) k.pop(); + k.push(P[i]); + } + + for (let i = n - 2, t = k.length + 1; i >= 0; i--) { + while (k.length >= t && C(k[k.length - 2], k[k.length - 1], P[i]) <= 0) k.pop(); + k.push(P[i]); + } + + k.pop(); + return k; +}; +export default findConvexHull; \ No newline at end of file diff --git a/tests/2_convex_hull/outputs/moonshotai_kimi-k2-thinking.js b/tests/2_convex_hull/outputs/moonshotai_kimi-k2-thinking.js index ef9c731..6cb0b05 100644 --- a/tests/2_convex_hull/outputs/moonshotai_kimi-k2-thinking.js +++ b/tests/2_convex_hull/outputs/moonshotai_kimi-k2-thinking.js @@ -1,24 +1,19 @@ -async function findConvexHull(points) { - const { default: _ } = await import('https://cdn.jsdelivr.net/npm/lodash@4/esm/lodash.js'); - - if (!points || points.length < 3) return [...(points || [])]; - - const pts = _.sortBy(_.uniqWith(points, (a, b) => a.x === b.x && a.y === b.y), ['x', 'y']); - - const cross = (o, a, b) => (a.x - o.x) * (b.y - o.y) - (a.y - o.y) * (b.x - o.x); - - const build = arr => { - const h = []; - for (const p of arr) { - while (h.length >= 2 && cross(h[h.length - 2], h[h.length - 1], p) <= 0) h.pop(); - h.push(p); - } - return h; - }; - - const lower = build(pts); - const upper = build([...pts].reverse()); - - return [...lower.slice(0, -1), ...upper.slice(0, -1)]; -} +const findConvexHull = async (pts) => { + const { sortBy, uniqBy } = await import('https://esm.sh/lodash-es@4'); + const cross = (a, b, c) => (b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x); + const sorted = sortBy(uniqBy(pts, p => `${p.x},${p.y}`), ['x', 'y']); + if (sorted.length < 3) return sorted; + const lower = [], upper = []; + for (const p of sorted) { + while (lower.length > 1 && cross(lower[lower.length-2], lower[lower.length-1], p) <= 0) lower.pop(); + lower.push(p); + } + for (let i = sorted.length - 1; i >= 0; i--) { + const p = sorted[i]; + while (upper.length > 1 && cross(upper[upper.length-2], upper[upper.length-1], p) <= 0) upper.pop(); + upper.push(p); + } + lower.pop(); upper.pop(); + return [...lower, ...upper]; +}; export default findConvexHull; \ No newline at end of file diff --git a/tests/2_convex_hull/outputs/openai_gpt-5.1-chat.js b/tests/2_convex_hull/outputs/openai_gpt-5.1-chat.js deleted file mode 100644 index e2b91bb..0000000 --- a/tests/2_convex_hull/outputs/openai_gpt-5.1-chat.js +++ /dev/null @@ -1,20 +0,0 @@ -export async function findConvexHull(p){ - const _=(await import('https://cdn.jsdelivr.net/npm/lodash-es@4.17.21/lodash.min.js')).default - p=_.uniqWith(p,_.isEqual) - p=_.sortBy(p,['x','y']) - const c=(a,b,d)=>(b.x-a.x)*(d.y-a.y)-(b.y-a.y)*(d.x-a.x) - const h=[] - for(const v of p){ - while(h.length>1&&c(h[h.length-2],h[h.length-1],v)<=0)h.pop() - h.push(v) - } - const u=[] - for(const v of [...p].reverse()){ - while(u.length>1&&c(u[u.length-2],u[u.length-1],v)<=0)u.pop() - u.push(v) - } - h.pop() - u.pop() - return [...h,...u] -} -export default findConvexHull; \ No newline at end of file diff --git a/tests/2_convex_hull/outputs/openai_gpt-5.1-codex.js b/tests/2_convex_hull/outputs/openai_gpt-5.1-codex.js index 1ce745a..d6e16fa 100644 --- a/tests/2_convex_hull/outputs/openai_gpt-5.1-codex.js +++ b/tests/2_convex_hull/outputs/openai_gpt-5.1-codex.js @@ -1,18 +1,21 @@ -async function findConvexHull(points) { - const {sortBy, uniqWith} = await import('https://cdn.jsdelivr.net/npm/lodash-es@4.17.21/lodash.js') - const ps = uniqWith(sortBy(points.map(({x, y}) => ({x: +x, y: +y})), ['x', 'y']), (a, b) => a.x === b.x && a.y === b.y) - if (ps.length < 2) return ps - const c = (o, a, b) => (a.x - o.x) * (b.y - o.y) - (a.y - o.y) * (b.x - o.x) - const lower = [] - for (const p of ps) { - while (lower.length > 1 && c(lower.at(-2), lower.at(-1), p) <= 0) lower.pop() - lower.push(p) +async function findConvexHull(points){ + const m=await import('https://cdn.skypack.dev/lodash?min') + const _=m.default||m + const pts=_.sortBy(_.uniqWith(points,(a,b)=>a.x===b.x&&a.y===b.y),['x','y']) + if(pts.length<3)return pts.slice() + const h=[] + const c=(o,a,b)=>(a.x-o.x)*(b.y-o.y)-(a.y-o.y)*(b.x-o.x) + for(const p of pts){ + while(h.length>1&&c(h.at(-2),h.at(-1),p)<=0)h.pop() + h.push(p) } - const upper = [] - for (const p of [...ps].reverse()) { - while (upper.length > 1 && c(upper.at(-2), upper.at(-1), p) <= 0) upper.pop() - upper.push(p) + const t=h.length+1 + for(let i=pts.length-2;i>=0;i--){ + const p=pts[i] + while(h.length>=t&&c(h.at(-2),h.at(-1),p)<=0)h.pop() + h.push(p) } - return lower.slice(0, -1).concat(upper.slice(0, -1)) + h.pop() + return h } export default findConvexHull; \ No newline at end of file diff --git a/tests/2_convex_hull/outputs/openrouter_sherlock-dash-alpha.js b/tests/2_convex_hull/outputs/openrouter_sherlock-dash-alpha.js deleted file mode 100644 index cc32fc5..0000000 --- a/tests/2_convex_hull/outputs/openrouter_sherlock-dash-alpha.js +++ /dev/null @@ -1,16 +0,0 @@ -async function findConvexHull(points) { - const {_, default: _} = await import('https://cdn.skypack.dev/lodash-es'); - const pts = _([...new Set(points.map(p=>`${p.x},${p.y}`))].map(s=>s.split(',').map(Number)).map(([x,y])=>({x,y}))); - const ccw=(a,b,c)=> (b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x); - const build=(pts,low)=> { - const hull=[]; - for(let p of pts){ - while(hull.length>1&&ccw(hull[hull.length-2],hull[hull.length-1],p)<=0) hull.pop(); - hull.push(p); - } - return hull.slice(0,low?hull.length:hull.length-1); - }; - if(pts.length<3) return pts; - return [...build(pts.sort((a,b)=>a.x-b.x||a.y-b.y),1),...build(pts.slice().reverse(),0)]; -} -export default findConvexHull; \ No newline at end of file diff --git a/tests/2_convex_hull/outputs/openrouter_sherlock-think-alpha.js b/tests/2_convex_hull/outputs/openrouter_sherlock-think-alpha.js index a1b8893..43368f4 100644 --- a/tests/2_convex_hull/outputs/openrouter_sherlock-think-alpha.js +++ b/tests/2_convex_hull/outputs/openrouter_sherlock-think-alpha.js @@ -1,19 +1,22 @@ -async function findConvexHull(pts){ -const _=(await import('https://esm.run/lodash@4.17.21')).default; -let p=_.uniqBy(_.sortBy(pts,['x','y']),q=>[q.x,q.y]); -if(p.length<=2)return p; -const cross=(o,a,b)=>(a.x-o.x)*(b.y-o.y)-(a.y-o.y)*(b.x-o.x); -let lower=[]; -for(let q of p){ -while(lower.length>=2&&cross(lower[lower.length-2],lower[lower.length-1],q)<=0)lower.pop(); -lower.push(q); -} -let upper=[]; -let rp=[...p].reverse(); -for(let q of rp){ -while(upper.length>=2&&cross(upper[upper.length-2],upper[upper.length-1],q)<=0)upper.pop(); -upper.push(q); -} -return lower.slice(0,-1).concat(upper.slice(0,-1)); +async function findConvexHull(points){ + const{default:L}=await import('https://cdn.skypack.dev/lodash-es'); + const{sortBy,uniqBy}=L; + let p=uniqBy(points,({x,y})=>`${x},${y}`); + if(p.length<2)return p; + p=sortBy(p,['x','y']); + const cross=(o,a,b)=>(a.x-o.x)*(b.y-o.y)-(a.y-o.y)*(b.x-o.x); + let l=[]; + for(let i=0;i=2&&cross(l[l.length-2],l[l.length-1],pt)<=0)l.pop(); + l.push(pt); + } + let u=[]; + for(let i=p.length-1;i>=0;i--){ + let pt=p[i]; + while(u.length>=2&&cross(u[u.length-2],u[u.length-1],pt)<=0)u.pop(); + u.push(pt); + } + return[...l.slice(0,-1),...u.slice(0,-1)]; } export default findConvexHull; \ No newline at end of file diff --git a/tests/3_lis/outputs/anthropic_claude-sonnet-4.5 TEMP_0.7.js b/tests/3_lis/outputs/anthropic_claude-sonnet-4.5 TEMP_0.7.js index 0920907..bb1cac7 100644 --- a/tests/3_lis/outputs/anthropic_claude-sonnet-4.5 TEMP_0.7.js +++ b/tests/3_lis/outputs/anthropic_claude-sonnet-4.5 TEMP_0.7.js @@ -1,7 +1,8 @@ -const findLISLength = async (arr) => { +async function findLISLength(arr) { + const { bisectLeft } = await import('https://cdn.jsdelivr.net/npm/d3-array@3/+esm'); + if (!arr?.length) return 0; - const { bisectLeft } = await import('https://cdn.skypack.dev/d3-array'); const tails = []; for (const num of arr) { @@ -10,5 +11,5 @@ const findLISLength = async (arr) => { } return tails.length; -}; +} export default findLISLength; \ No newline at end of file diff --git a/tests/3_lis/outputs/google_gemini-2.5-pro.js b/tests/3_lis/outputs/google_gemini-2.5-pro.js index e6ea665..f624b40 100644 --- a/tests/3_lis/outputs/google_gemini-2.5-pro.js +++ b/tests/3_lis/outputs/google_gemini-2.5-pro.js @@ -1,16 +1,16 @@ -const findLISLength = async (nums) => { +async function findLISLength(nums) { if (!nums?.length) { return 0; } - const { bisectLeft } = await import('https://esm.sh/d3-array'); - - const tails = []; + const { bisectLeft } = await import('https://cdn.jsdelivr.net/npm/d3-array@3/+esm'); + + const sub = []; for (const num of nums) { - tails[bisectLeft(tails, num)] = num; + sub[bisectLeft(sub, num)] = num; } - return tails.length; -}; + return sub.length; +} export default findLISLength; \ No newline at end of file diff --git a/tests/3_lis/outputs/google_gemini-3-pro-preview.js b/tests/3_lis/outputs/google_gemini-3-pro-preview.js new file mode 100644 index 0000000..40e7d2d --- /dev/null +++ b/tests/3_lis/outputs/google_gemini-3-pro-preview.js @@ -0,0 +1,7 @@ +const findLISLength = async arr => { + const { bisectLeft } = await import('https://esm.sh/d3-array') + const tails = [] + for (const n of arr) tails[bisectLeft(tails, n)] = n + return tails.length +} +export default findLISLength; \ No newline at end of file diff --git a/tests/3_lis/outputs/moonshotai_kimi-k2-thinking.js b/tests/3_lis/outputs/moonshotai_kimi-k2-thinking.js index aaa7cca..6062a1f 100644 --- a/tests/3_lis/outputs/moonshotai_kimi-k2-thinking.js +++ b/tests/3_lis/outputs/moonshotai_kimi-k2-thinking.js @@ -1,7 +1,12 @@ -async function findLISLength(nums){ - const{bisectLeft}=await import('https://cdn.skypack.dev/d3-array'); - const tails=[]; - for(const n of nums)tails[bisectLeft(tails,n)]=n; - return tails.length; -} +export const findLISLength = async (arr) => { + if (!Array.isArray(arr) || !arr.length) return 0; + try { + const { bisectLeft } = await import('https://cdn.skypack.dev/d3-array@3'); + const t = []; + for (const v of arr) t[bisectLeft(t, v)] = v; + return t.length; + } catch { + return 0; + } +}; export default findLISLength; \ No newline at end of file diff --git a/tests/3_lis/outputs/openai_gpt-5.1-chat.js b/tests/3_lis/outputs/openai_gpt-5.1-chat.js deleted file mode 100644 index 9962564..0000000 --- a/tests/3_lis/outputs/openai_gpt-5.1-chat.js +++ /dev/null @@ -1,10 +0,0 @@ -async function findLISLength(a) { - const {bisectLeft} = await import("https://cdn.jsdelivr.net/npm/d3-array@3/+esm"); - const t = []; - for (const x of a) { - const i = bisectLeft(t, x); - t[i] = x; - } - return t.length; -} -export default findLISLength; \ No newline at end of file diff --git a/tests/3_lis/outputs/openai_gpt-5.1-codex.js b/tests/3_lis/outputs/openai_gpt-5.1-codex.js index 9b88a0c..f7942fe 100644 --- a/tests/3_lis/outputs/openai_gpt-5.1-codex.js +++ b/tests/3_lis/outputs/openai_gpt-5.1-codex.js @@ -1,7 +1,11 @@ -async function findLISLength(a){ - const {bisectLeft:b}=await import('https://cdn.jsdelivr.net/npm/d3-array@3/+esm') - const t=[] - for(const n of a)t[b(t,n)]=n - return t.length +const findLISLength = async nums => { + if (!Array.isArray(nums)) throw new TypeError('Expected array') + const { bisectLeft } = await import('https://cdn.jsdelivr.net/npm/d3-array@3/+esm') + const tails = [] + for (const v of nums) { + const i = bisectLeft(tails, v) + i === tails.length ? tails.push(v) : tails[i] = v + } + return tails.length } export default findLISLength; \ No newline at end of file diff --git a/tests/3_lis/outputs/openrouter_sherlock-dash-alpha.js b/tests/3_lis/outputs/openrouter_sherlock-dash-alpha.js deleted file mode 100644 index 27c0dc5..0000000 --- a/tests/3_lis/outputs/openrouter_sherlock-dash-alpha.js +++ /dev/null @@ -1,12 +0,0 @@ -async function findLISLength(arr) { - const {bisectLeft} = await import('https://cdn.skypack.dev/d3-array'); - if(!arr.length) return 0; - const tails = []; - for(const x of arr) { - const i = bisectLeft(tails, x); - if(i === tails.length) tails.push(x); - else tails[i] = x; - } - return tails.length; -} -export default findLISLength; \ No newline at end of file diff --git a/tests/3_lis/outputs/openrouter_sherlock-think-alpha.js b/tests/3_lis/outputs/openrouter_sherlock-think-alpha.js index 7dd7dbe..3fd8b46 100644 --- a/tests/3_lis/outputs/openrouter_sherlock-think-alpha.js +++ b/tests/3_lis/outputs/openrouter_sherlock-think-alpha.js @@ -1,14 +1,2 @@ -async function findLISLength(arr) { - const {bisectLeft} = await import('https://cdn.skypack.dev/d3-array'); - let tails = []; - for (let num of arr) { - let i = bisectLeft(tails, num); - if (i === tails.length) { - tails.push(num); - } else { - tails[i] = num; - } - } - return tails.length; -} +async function findLISLength(arr){const{bisectLeft}=await import('https://cdn.skypack.dev/d3-array');let tails=[];for(const num of arr){const i=bisectLeft(tails,num);i===tails.length?tails.push(num):tails[i]=num;}return tails.length;} export default findLISLength; \ No newline at end of file diff --git a/tests/4_determinant/outputs/google_gemini-2.5-pro.js b/tests/4_determinant/outputs/google_gemini-2.5-pro.js index 2c9565f..e551fc7 100644 --- a/tests/4_determinant/outputs/google_gemini-2.5-pro.js +++ b/tests/4_determinant/outputs/google_gemini-2.5-pro.js @@ -1,5 +1,5 @@ const calculateDeterminant = async (matrix) => { - const { det } = await import('https://cdn.jsdelivr.net/npm/mathjs@13.0.0/+esm'); + const { det } = await import('https://cdn.jsdelivr.net/npm/mathjs@13.0.0/es/index.js'); return det(matrix); }; export default calculateDeterminant; \ No newline at end of file diff --git a/tests/4_determinant/outputs/google_gemini-3-pro-preview.js b/tests/4_determinant/outputs/google_gemini-3-pro-preview.js new file mode 100644 index 0000000..84bcba8 --- /dev/null +++ b/tests/4_determinant/outputs/google_gemini-3-pro-preview.js @@ -0,0 +1,5 @@ +const calculateDeterminant = async m => { + const { det } = await import('https://esm.sh/mathjs') + return det(m) +} +export default calculateDeterminant; \ No newline at end of file diff --git a/tests/4_determinant/outputs/moonshotai_kimi-k2-thinking.js b/tests/4_determinant/outputs/moonshotai_kimi-k2-thinking.js index 72358f4..a57f4b5 100644 --- a/tests/4_determinant/outputs/moonshotai_kimi-k2-thinking.js +++ b/tests/4_determinant/outputs/moonshotai_kimi-k2-thinking.js @@ -1,8 +1,13 @@ -let math; +const URL = 'https://cdn.jsdelivr.net/npm/mathjs@11.11.0/+esm'; +let det; + async function calculateDeterminant(m) { - const n = m?.length; - if (!n || m.some(r => !Array.isArray(r) || r.length !== n)) throw new Error('Invalid matrix'); - math ||= await import('https://cdn.jsdelivr.net/npm/mathjs@11.11.0/+esm'); - return math.det(m); + const v = Array.isArray(m) && m.length && m.every(r => Array.isArray(r) && r.length === m.length); + if (!v) throw new TypeError('Invalid matrix'); + + det ||= await import(URL).then(m => m.det).catch(() => { throw new Error('Load failed'); }); + + try { return det(m); } + catch { throw new Error('Calc failed'); } } export default calculateDeterminant; \ No newline at end of file diff --git a/tests/4_determinant/outputs/openai_gpt-5.1-chat.js b/tests/4_determinant/outputs/openai_gpt-5.1-chat.js deleted file mode 100644 index 776a2ca..0000000 --- a/tests/4_determinant/outputs/openai_gpt-5.1-chat.js +++ /dev/null @@ -1,5 +0,0 @@ -async function calculateDeterminant(m){ - const {det}=await import('https://cdn.jsdelivr.net/npm/mathjs@14.0.0/+esm') - return det(m) -} -export default calculateDeterminant; \ No newline at end of file diff --git a/tests/4_determinant/outputs/openai_gpt-5.1-codex.js b/tests/4_determinant/outputs/openai_gpt-5.1-codex.js index 5cbc3ee..5b25537 100644 --- a/tests/4_determinant/outputs/openai_gpt-5.1-codex.js +++ b/tests/4_determinant/outputs/openai_gpt-5.1-codex.js @@ -1,5 +1,5 @@ -const calculateDeterminant=async m=>{ - const {det}=await import('https://cdn.skypack.dev/mathjs') +async function calculateDeterminant(m){ + const {det}=await import('https://cdn.jsdelivr.net/npm/mathjs@11.11.1/+esm') return det(m) } export default calculateDeterminant; \ No newline at end of file diff --git a/tests/4_determinant/outputs/openrouter_sherlock-dash-alpha.js b/tests/4_determinant/outputs/openrouter_sherlock-dash-alpha.js deleted file mode 100644 index d2c12f3..0000000 --- a/tests/4_determinant/outputs/openrouter_sherlock-dash-alpha.js +++ /dev/null @@ -1,5 +0,0 @@ -const calculateDeterminant=async m=>{ - const{math}=await import('https://cdn.jsdelivr.net/npm/mathjs@12.4.2/lib/browser/math.js'); - return math.det(m); -}; -export default calculateDeterminant; \ No newline at end of file diff --git a/tests/4_determinant/outputs/openrouter_sherlock-think-alpha.js b/tests/4_determinant/outputs/openrouter_sherlock-think-alpha.js index f1a7ebf..e769c76 100644 --- a/tests/4_determinant/outputs/openrouter_sherlock-think-alpha.js +++ b/tests/4_determinant/outputs/openrouter_sherlock-think-alpha.js @@ -1,5 +1,2 @@ -async function calculateDeterminant(matrix) { - const { det } = await import('https://esm.sh/mathjs'); - return det(matrix); -} +async function calculateDeterminant(matrix){const math=await import('https://esm.sh/mathjs');return math.det(matrix);} export default calculateDeterminant; \ No newline at end of file diff --git a/tests/5_markdown_parser/outputs/anthropic_claude-sonnet-4.5 TEMP_0.7.js b/tests/5_markdown_parser/outputs/anthropic_claude-sonnet-4.5 TEMP_0.7.js index 9bf74ee..c273bf1 100644 --- a/tests/5_markdown_parser/outputs/anthropic_claude-sonnet-4.5 TEMP_0.7.js +++ b/tests/5_markdown_parser/outputs/anthropic_claude-sonnet-4.5 TEMP_0.7.js @@ -1,5 +1,5 @@ const parseMarkdown = async (md) => { - const { marked } = await import('https://cdn.jsdelivr.net/npm/marked@11.1.1/+esm'); + const { marked } = await import('https://cdn.jsdelivr.net/npm/marked@11/+esm'); return marked.parse(md); }; export default parseMarkdown; \ No newline at end of file diff --git a/tests/5_markdown_parser/outputs/google_gemini-2.5-pro.js b/tests/5_markdown_parser/outputs/google_gemini-2.5-pro.js index c692ded..cd0859f 100644 --- a/tests/5_markdown_parser/outputs/google_gemini-2.5-pro.js +++ b/tests/5_markdown_parser/outputs/google_gemini-2.5-pro.js @@ -1,6 +1,12 @@ -const parseMarkdown = async (markdown) => { - const cdnUrl = 'https://cdn.jsdelivr.net/npm/marked@13.0.0/lib/marked.esm.js'; - const { marked } = await import(cdnUrl); - return marked.parse(markdown ?? ''); +const parseMarkdown = async (markdownText) => { + const cdnUrl = 'https://cdn.jsdelivr.net/npm/marked@13.0.2/lib/marked.esm.js'; + + try { + const { marked } = await import(cdnUrl); + return marked.parse(markdownText || ''); + } catch (err) { + console.error(`Failed to parse markdown: ${err}`); + return markdownText || ''; + } }; export default parseMarkdown; \ No newline at end of file diff --git a/tests/5_markdown_parser/outputs/google_gemini-3-pro-preview.js b/tests/5_markdown_parser/outputs/google_gemini-3-pro-preview.js new file mode 100644 index 0000000..e74ed36 --- /dev/null +++ b/tests/5_markdown_parser/outputs/google_gemini-3-pro-preview.js @@ -0,0 +1,5 @@ +const parseMarkdown = async md => { + const { parse } = await import('https://cdn.jsdelivr.net/npm/marked@12.0.1/lib/marked.esm.js') + return parse(md) +} +export default parseMarkdown; \ No newline at end of file diff --git a/tests/5_markdown_parser/outputs/moonshotai_kimi-k2-thinking.js b/tests/5_markdown_parser/outputs/moonshotai_kimi-k2-thinking.js index 25d0bfd..e4c1e5f 100644 --- a/tests/5_markdown_parser/outputs/moonshotai_kimi-k2-thinking.js +++ b/tests/5_markdown_parser/outputs/moonshotai_kimi-k2-thinking.js @@ -1,9 +1,13 @@ -const parseMarkdown = async m => { +async function parseMarkdown(md) { + const u = 'https://cdn.jsdelivr.net/npm/marked@9/lib/marked.esm.js'; + const o = {gfm:true,breaks:true,headerIds:false,mangle:false}; + try { - const {marked} = await import('https://esm.sh/marked'); - return marked.parse(m); - } catch (e) { - return `
${e.message}
`; + const {marked} = await import(u); + marked.setOptions(o); + return marked.parse(md); + } catch(e) { + return `

${e.message}

`; } -}; +} export default parseMarkdown; \ No newline at end of file diff --git a/tests/5_markdown_parser/outputs/openai_gpt-5.1-chat.js b/tests/5_markdown_parser/outputs/openai_gpt-5.1-chat.js deleted file mode 100644 index ddbc499..0000000 --- a/tests/5_markdown_parser/outputs/openai_gpt-5.1-chat.js +++ /dev/null @@ -1,5 +0,0 @@ -export async function parseMarkdown(m){ - const {marked}=await import('https://cdn.jsdelivr.net/npm/marked/lib/marked.esm.js') - return marked.parse(m) -} -export default parseMarkdown; \ No newline at end of file diff --git a/tests/5_markdown_parser/outputs/openai_gpt-5.1-codex.js b/tests/5_markdown_parser/outputs/openai_gpt-5.1-codex.js index d9611bf..afdd4e4 100644 --- a/tests/5_markdown_parser/outputs/openai_gpt-5.1-codex.js +++ b/tests/5_markdown_parser/outputs/openai_gpt-5.1-codex.js @@ -1,5 +1,5 @@ -const parseMarkdown=async(md='')=>{ - const{marked}=await import('https://cdn.jsdelivr.net/npm/marked/lib/marked.esm.js'); - return marked.parse(md); -}; +const parseMarkdown=async m=>{ + const {marked}=await import('https://cdn.jsdelivr.net/npm/marked@11.1.0/lib/marked.esm.js') + return marked.parse(m) +} export default parseMarkdown; \ No newline at end of file diff --git a/tests/5_markdown_parser/outputs/openrouter_sherlock-dash-alpha.js b/tests/5_markdown_parser/outputs/openrouter_sherlock-dash-alpha.js deleted file mode 100644 index 39e1b9e..0000000 --- a/tests/5_markdown_parser/outputs/openrouter_sherlock-dash-alpha.js +++ /dev/null @@ -1,35 +0,0 @@ -async function parseMarkdown(md) { - const { default: marked } = await import('https://cdn.skypack.dev/marked@14.1.2'); - marked.use({ - breaks: true, - gfm: true, - async tokenize(src) { - const tokens = marked.lexer(src); - for (const token of tokens) { - if (token.type === 'list') { - token.ordered = token.ordered || false; - token.loose = !!token.items.find(item => item.text.includes('\n')); - } - } - return tokens; - }, - renderer: { - heading(text, level) { return `${text}`; }, - strong(text) { return `${text}`; }, - em(text) { return `${text}`; }, - codespan(text) { return `${text}`; }, - link(href, title, text) { return `${text}`; }, - code(code, infostring) { - const lang = (infostring || '').match(/^([a-z0-9]+)/i); - return `
${code}
`; - }, - list(body, ordered) { - const type = ordered ? 'ol' : 'ul'; - return `<${type}>${body}`; - }, - blockquote(quote) { return `
${quote}
`; } - } - }); - return marked.parse(md); -} -export default parseMarkdown; \ No newline at end of file diff --git a/tests/5_markdown_parser/outputs/openrouter_sherlock-think-alpha.js b/tests/5_markdown_parser/outputs/openrouter_sherlock-think-alpha.js index 0bc2d8f..ed2249e 100644 --- a/tests/5_markdown_parser/outputs/openrouter_sherlock-think-alpha.js +++ b/tests/5_markdown_parser/outputs/openrouter_sherlock-think-alpha.js @@ -1,5 +1,5 @@ -async function parseMarkdown(text) { - const {marked} = await import('https://unpkg.com/marked@14.1.2?module'); - return marked(text); +async function parseMarkdown(md){ + const{marked}=await import('https://esm.sh/marked'); + return marked.parse(md); } export default parseMarkdown; \ No newline at end of file diff --git a/tests/6_csv_processor/outputs/anthropic_claude-sonnet-4.5 TEMP_0.7.js b/tests/6_csv_processor/outputs/anthropic_claude-sonnet-4.5 TEMP_0.7.js index bf8bb8e..f167448 100644 --- a/tests/6_csv_processor/outputs/anthropic_claude-sonnet-4.5 TEMP_0.7.js +++ b/tests/6_csv_processor/outputs/anthropic_claude-sonnet-4.5 TEMP_0.7.js @@ -1,9 +1,9 @@ -const processCSV = async (csv, { filterColumn, filterValue, groupBy, aggregateColumn, operation }) => { - const { parse } = await import('https://cdn.skypack.dev/csv-parse/sync'); +const processCSV = async (csvString, { filterColumn, filterValue, groupBy, aggregateColumn, operation }) => { + const { default: Papa } = await import('https://cdn.jsdelivr.net/npm/[email protected]/+esm'); - const records = parse(csv, { columns: true, skip_empty_lines: true }); + const { data } = Papa.parse(csvString, { header: true, skipEmptyLines: true }); - const filtered = records.filter(r => r[filterColumn] == filterValue); + const filtered = data.filter(row => row[filterColumn] == filterValue); const groups = filtered.reduce((acc, row) => { const key = row[groupBy]; @@ -12,12 +12,12 @@ const processCSV = async (csv, { filterColumn, filterValue, groupBy, aggregateCo }, {}); return Object.entries(groups).map(([key, rows]) => { - const vals = rows.map(r => Number(r[aggregateColumn]) || 0); - const sum = vals.reduce((a, b) => a + b, 0); + const values = rows.map(r => +r[aggregateColumn] || 0); + const sum = values.reduce((a, b) => a + b, 0); return { [groupBy]: key, - result: operation === 'sum' ? sum : operation === 'avg' ? sum / vals.length : vals.length + result: operation === 'sum' ? sum : operation === 'avg' ? sum / values.length : rows.length }; }); }; diff --git a/tests/6_csv_processor/outputs/google_gemini-2.5-pro.js b/tests/6_csv_processor/outputs/google_gemini-2.5-pro.js index 51dea76..999807c 100644 --- a/tests/6_csv_processor/outputs/google_gemini-2.5-pro.js +++ b/tests/6_csv_processor/outputs/google_gemini-2.5-pro.js @@ -1,39 +1,38 @@ -async function processCSV(csv, { - filterColumn, - filterValue, - groupBy, - aggregateColumn, - operation, -}) { - const { default: Papa } = await import( - 'https://cdn.jsdelivr.net/npm/papaparse@5.4.1/papaparse.min.js' - ); +async function processCSV(csvString, config) { + const { + filterColumn, + filterValue, + groupBy, + aggregateColumn, + operation + } = config; - const { data } = Papa.parse(csv, { header: true, skipEmptyLines: true }); + const { default: Papa } = await import('https://cdn.jsdelivr.net/npm/papaparse@5.4.1/+esm'); - const groups = data.reduce((acc, row) => { - if (row[filterColumn] != filterValue) { + const { data } = Papa.parse(csvString, { + header: true, + skipEmptyLines: true + }); + + const groups = data + .filter(row => row[filterColumn] == filterValue) + .reduce((acc, row) => { + const key = row[groupBy]; + const val = Number(row[aggregateColumn]) || 0; + + if (operation === 'avg') { + const group = (acc[key] ??= { sum: 0, count: 0 }); + group.sum += val; + group.count++; + } else { + acc[key] = (acc[key] ?? 0) + (operation === 'sum' ? val : 1); + } return acc; - } + }, {}); - const key = row[groupBy]; - const stats = acc.get(key) || { sum: 0, count: 0 }; - - stats.sum += Number(row[aggregateColumn]) || 0; - stats.count++; - - return acc.set(key, stats); - }, new Map()); - - const aggregators = { - sum: ({ sum }) => sum, - avg: ({ sum, count }) => (count ? sum / count : 0), - count: ({ count }) => count, - }; - - return Array.from(groups, ([key, stats]) => ({ - [groupBy]: key, - result: aggregators[operation](stats), + return Object.entries(groups).map(([groupValue, aggData]) => ({ + [groupBy]: groupValue, + result: operation === 'avg' ? aggData.sum / aggData.count : aggData, })); } export default processCSV; \ No newline at end of file diff --git a/tests/6_csv_processor/outputs/google_gemini-3-pro-preview.js b/tests/6_csv_processor/outputs/google_gemini-3-pro-preview.js new file mode 100644 index 0000000..7509c02 --- /dev/null +++ b/tests/6_csv_processor/outputs/google_gemini-3-pro-preview.js @@ -0,0 +1,22 @@ +const processCSV = async (csv, { filterColumn: fKey, filterValue: fVal, groupBy: gKey, aggregateColumn: aKey, operation: op }) => { + const { parse } = await import('https://cdn.jsdelivr.net/npm/papaparse@5.4.1/+esm') + const { data } = parse(csv, { header: true, skipEmptyLines: true }) + + const groups = data.reduce((acc, row) => { + if (row[fKey] == fVal) { + const key = row[gKey] + const val = +row[aKey] || 0 + const rec = acc[key] || { sum: 0, count: 0 } + rec.sum += val + rec.count++ + acc[key] = rec + } + return acc + }, {}) + + return Object.entries(groups).map(([key, { sum, count }]) => ({ + [gKey]: key, + result: op === 'count' ? count : op === 'avg' ? sum / count : sum + })) +} +export default processCSV; \ No newline at end of file diff --git a/tests/6_csv_processor/outputs/moonshotai_kimi-k2-thinking.js b/tests/6_csv_processor/outputs/moonshotai_kimi-k2-thinking.js index 0d546af..aa33d84 100644 --- a/tests/6_csv_processor/outputs/moonshotai_kimi-k2-thinking.js +++ b/tests/6_csv_processor/outputs/moonshotai_kimi-k2-thinking.js @@ -1,19 +1,15 @@ -async function processCSV(csv, cfg) { +async function processCSV(csv, { filterColumn:f, filterValue:v, groupBy:g, aggregateColumn:a, operation:o }) { const [{ default: Papa }, { default: _ }] = await Promise.all([ import('https://cdn.jsdelivr.net/npm/papaparse@5.4.1/+esm'), import('https://cdn.jsdelivr.net/npm/lodash@4.17.21/+esm') ]); - const filtered = Papa.parse(csv, { header: true, dynamicTyping: true }).data - .filter(r => r[cfg.filterColumn] == cfg.filterValue); + const data = Papa.parse(csv, { header:true, dynamicTyping:true }).data.filter(r => r[f] == v); - return Object.entries(_.groupBy(filtered, cfg.groupBy)).map(([k, v]) => { - const sum = v.reduce((s, r) => s + (Number(r[cfg.aggregateColumn]) || 0), 0); - return { - [cfg.groupBy]: k, - result: cfg.operation === 'count' ? v.length : - cfg.operation === 'avg' ? sum / v.length : sum - }; + return Object.entries(_.groupBy(data, g)).map(([k, d]) => { + const n = d.map(r => (x = Number(r[a]), isNaN(x) ? 0 : x)); + const s = n.reduce((p, c) => p + c, 0); + return { [g]: k, result: o === 'count' ? d.length : o === 'avg' ? s / n.length : s }; }); } export default processCSV; \ No newline at end of file diff --git a/tests/6_csv_processor/outputs/openai_gpt-5.1-chat.js b/tests/6_csv_processor/outputs/openai_gpt-5.1-chat.js deleted file mode 100644 index 31c4d81..0000000 --- a/tests/6_csv_processor/outputs/openai_gpt-5.1-chat.js +++ /dev/null @@ -1,22 +0,0 @@ -async function processCSV(csv, cfg) { - const p = await import("https://cdn.jsdelivr.net/npm/papaparse@5.4.1/papaparse.min.js"); - const f = p.parse(csv, { header: true }).data.filter(r => r[cfg.filterColumn] == cfg.filterValue); - const g = {}; - for (const r of f) { - const k = r[cfg.groupBy]; - if (!g[k]) g[k] = []; - g[k].push(r); - } - const out = []; - for (const k in g) { - const rows = g[k]; - let nums = rows.map(r => +r[cfg.aggregateColumn] || 0); - let res = 0; - if (cfg.operation === "sum") res = nums.reduce((a, b) => a + b, 0); - else if (cfg.operation === "avg") res = nums.reduce((a, b) => a + b, 0) / nums.length; - else if (cfg.operation === "count") res = rows.length; - out.push({ [cfg.groupBy]: k, result: res }); - } - return out; -} -export default processCSV; \ No newline at end of file diff --git a/tests/6_csv_processor/outputs/openai_gpt-5.1-codex.js b/tests/6_csv_processor/outputs/openai_gpt-5.1-codex.js index fd1786d..8bd3bf8 100644 --- a/tests/6_csv_processor/outputs/openai_gpt-5.1-codex.js +++ b/tests/6_csv_processor/outputs/openai_gpt-5.1-codex.js @@ -1,16 +1,20 @@ async function processCSV(csv,cfg){ - const [{Papa},{groupBy:gb}]=await Promise.all([ - import('https://cdn.jsdelivr.net/npm/papaparse@5.4.1/papaparse.min.mjs'), - import('https://cdn.jsdelivr.net/npm/lodash-es@4.17.21/lodash.js') - ]) - const {filterColumn:fc,filterValue:fv,groupBy:gbk,aggregateColumn:ac,operation:op}=cfg - const rows=Papa.parse(csv,{header:!0,skipEmptyLines:!0}).data.filter(r=>r&&r[fc]==fv) - const grouped=gb(rows,r=>r?.[gbk]??'') - return Object.entries(grouped).map(([k,arr])=>{ - const nums=arr.map(r=>{const n=+r[ac];return Number.isFinite(n)?n:0}) - const sum=nums.reduce((a,b)=>a+b,0) - const result=op==='sum'?sum:op==='avg'?sum/nums.length:arr.length - return {[gbk]:k,result} - }) + const[{default:Papa},{groupBy}]=await Promise.all([ + import('https://cdn.jsdelivr.net/npm/papaparse@5.4.1/+esm'), + import('https://cdn.jsdelivr.net/npm/lodash-es@4.17.21/+esm') + ]); + const{filterColumn:f,filterValue:v,groupBy:g,aggregateColumn:a,operation:o}=cfg; + const rows=Papa.parse(csv,{header:true,skipEmptyLines:true}).data.filter(r=>r[f]==v); + const groups=groupBy(rows,r=>r[g]); + return Object.entries(groups).map(([k,list])=>{ + const nums=list.map(r=>{ + const n=Number(r[a]); + return Number.isFinite(n)?n:0; + }); + const sum=nums.reduce((t,n)=>t+n,0); + const count=list.length; + const result=o==='sum'?sum:o==='avg'?sum/count:count; + return{[g]:k,result}; + }); } export default processCSV; \ No newline at end of file diff --git a/tests/6_csv_processor/outputs/openrouter_sherlock-dash-alpha.js b/tests/6_csv_processor/outputs/openrouter_sherlock-dash-alpha.js deleted file mode 100644 index 5e01fef..0000000 --- a/tests/6_csv_processor/outputs/openrouter_sherlock-dash-alpha.js +++ /dev/null @@ -1,2 +0,0 @@ -async function processCSV(csv,cfg){const{Papa}=await import('https://cdn.jsdelivr.net/npm/papaparse@5.4.1/papaparse.min.js');const{groupBy,mean,sum}=await import('https://cdn.jsdelivr.net/npm/@jazzband/lodash-deep@1.1.3/lodash-deep.min.js');const{data,meta}=Papa.parse(csv,{header:!0});const rows=data.filter(r=>r[cfg.filterColumn]==cfg.filterValue);const num=(v)=>+v||0;const grouped=groupBy(rows,r=>r[cfg.groupBy]);return Object.entries(grouped).map(([k,v])=>({ [cfg.groupBy]:k,result:cfg.operation==='sum'?sum(v.map(r=>num(r[cfg.aggregateColumn]))):cfg.operation==='avg'?mean(v.map(r=>num(r[cfg.aggregateColumn]))):v.length}))} -export default processCSV; \ No newline at end of file diff --git a/tests/6_csv_processor/outputs/openrouter_sherlock-think-alpha.js b/tests/6_csv_processor/outputs/openrouter_sherlock-think-alpha.js index 532bb6b..f3204e4 100644 --- a/tests/6_csv_processor/outputs/openrouter_sherlock-think-alpha.js +++ b/tests/6_csv_processor/outputs/openrouter_sherlock-think-alpha.js @@ -1,19 +1,27 @@ -async function processCSV(csvString,config){ - const{default:Papa}=await import('https://esm.sh/papaparse'); - const{filterColumn:fc,filterValue:fv,groupBy:gb,aggregateColumn:ac,operation:op}=config; - const parsed=Papa.parse(csvString,{header:true}).data; - const filtered=parsed.filter(r=>r[fc]==fv); - const groups=filtered.reduce((acc,r)=>{ - const k=r[gb]; - const v=Number(r[ac])||0; - if(!acc[k])acc[k]={s:0,c:0}; - acc[k].s+=v; - acc[k].c++; - return acc; - },{}); - return Object.entries(groups).map(([k,g])=>{ - const res=op==='count'?g.c:op==='sum'?g.s:g.s/g.c; - return{[gb]:k,result:res}; - }); +async function processCSV(csv,{filterColumn,filterValue,groupBy,aggregateColumn,operation}){ + const Papa=(await import('https://cdn.jsdelivr.net/npm/papaparse@5/+esm')).default; + const{data}=Papa.parse(csv,{header:true,skipEmptyLines:true}); + const groups=new Map(); + for(const row of data){ + if(row[filterColumn]==filterValue){ + const key=row[groupBy]; + const val=Number(row[aggregateColumn])||0; + const g=groups.get(key)||{sum:0,count:0}; + g.sum+=val; + g.count++; + groups.set(key,g); + } + } + const result=[]; + for(const[key,g]of groups){ + let res; + switch(operation){ + case'sum':res=g.sum;break; + case'avg':res=g.sum/g.count;break; + case'count':res=g.count;break; + } + result.push({[groupBy]:key,result:res}); + } + return result; } export default processCSV; \ No newline at end of file diff --git a/tests/7_scheduler/outputs/anthropic_claude-sonnet-4.5 TEMP_0.7.js b/tests/7_scheduler/outputs/anthropic_claude-sonnet-4.5 TEMP_0.7.js index b07f872..999a2ae 100644 --- a/tests/7_scheduler/outputs/anthropic_claude-sonnet-4.5 TEMP_0.7.js +++ b/tests/7_scheduler/outputs/anthropic_claude-sonnet-4.5 TEMP_0.7.js @@ -1,81 +1,71 @@ -async function findAvailableSlots(cal1, cal2, constraints) { - const { parse, format, addMinutes, isWithinInterval, isBefore, isAfter, startOfDay, setHours, setMinutes } = await import('https://cdn.jsdelivr.net/npm/date-fns@3.0.0/+esm'); +const findAvailableSlots = async (cal1, cal2, constraints) => { + const { default: dayjs } = await import('https://cdn.jsdelivr.net/npm/dayjs@1.11.10/+esm'); + const { default: isBetween } = await import('https://cdn.jsdelivr.net/npm/dayjs@1.11.10/plugin/isBetween.js/+esm'); + const { default: customParseFormat } = await import('https://cdn.jsdelivr.net/npm/dayjs@1.11.10/plugin/customParseFormat.js/+esm'); + dayjs.extend(isBetween); + dayjs.extend(customParseFormat); + const { durationMinutes, searchRange, workHours } = constraints; - const duration = durationMinutes; - - const parseTime = (dateStr) => parse(dateStr, "yyyy-MM-dd'T'HH:mm:ss.SSSxxx", new Date()); - const toISO = (date) => format(date, "yyyy-MM-dd'T'HH:mm:ss.SSSxxx"); - - const rangeStart = parseTime(searchRange.start); - const rangeEnd = parseTime(searchRange.end); - - const [whStart, whEnd] = workHours.start.split(':').map(Number); - const [whEndH, whEndM] = workHours.end.split(':').map(Number); - - const allBusy = [...cal1, ...cal2].map(slot => ({ - start: parseTime(slot.start), - end: parseTime(slot.end) - })).sort((a, b) => a.start - b.start); - + const searchStart = dayjs(searchRange.start); + const searchEnd = dayjs(searchRange.end); + + const allBusy = [...cal1, ...cal2] + .map(({ start, end }) => ({ start: dayjs(start), end: dayjs(end) })) + .sort((a, b) => a.start.valueOf() - b.start.valueOf()); + const merged = []; for (const slot of allBusy) { - if (!merged.length || isBefore(merged[merged.length - 1].end, slot.start)) { - merged.push({ ...slot }); + if (!merged.length || merged[merged.length - 1].end.isBefore(slot.start)) { + merged.push({ start: slot.start, end: slot.end }); } else { - merged[merged.length - 1].end = isAfter(slot.end, merged[merged.length - 1].end) - ? slot.end - : merged[merged.length - 1].end; + merged[merged.length - 1].end = dayjs.max(merged[merged.length - 1].end, slot.end); } } - + const freePeriods = []; - let current = rangeStart; + let current = searchStart; for (const busy of merged) { - if (isBefore(current, busy.start)) { + if (current.isBefore(busy.start)) { freePeriods.push({ start: current, end: busy.start }); } - current = isAfter(busy.end, current) ? busy.end : current; + current = dayjs.max(current, busy.end); } - if (isBefore(current, rangeEnd)) { - freePeriods.push({ start: current, end: rangeEnd }); + if (current.isBefore(searchEnd)) { + freePeriods.push({ start: current, end: searchEnd }); } - - const isInWorkHours = (date) => { - const day = startOfDay(date); - const workStart = setMinutes(setHours(day, whStart), whEnd > 0 ? 0 : 0); - const workEnd = setMinutes(setHours(day, whEndH), whEndM); - return isWithinInterval(date, { start: workStart, end: workEnd }); + + const isWithinWorkHours = (slotStart, slotEnd) => { + const date = slotStart.format('YYYY-MM-DD'); + const workStart = dayjs(`${date} ${workHours.start}`, 'YYYY-MM-DD HH:mm'); + const workEnd = dayjs(`${date} ${workHours.end}`, 'YYYY-MM-DD HH:mm'); + + return !slotStart.isBefore(workStart) && !slotEnd.isAfter(workEnd); }; - + const slots = []; for (const period of freePeriods) { let slotStart = period.start; - while (true) { - const slotEnd = addMinutes(slotStart, duration); + while (slotStart.add(durationMinutes, 'minute').isSameOrBefore(period.end)) { + const slotEnd = slotStart.add(durationMinutes, 'minute'); - if (isAfter(slotEnd, period.end)) break; - - if (isInWorkHours(slotStart) && isInWorkHours(slotEnd)) { - const day1 = startOfDay(slotStart); - const day2 = startOfDay(slotEnd); - - if (day1.getTime() === day2.getTime()) { - slots.push({ - start: toISO(slotStart), - end: toISO(slotEnd) - }); - } + if (isWithinWorkHours(slotStart, slotEnd) && + !slotStart.isBefore(searchStart) && + !slotEnd.isAfter(searchEnd)) { + slots.push({ + start: slotStart.toISOString(), + end: slotEnd.toISOString() + }); } slotStart = slotEnd; } } - + return slots; -} +}; export default findAvailableSlots; \ No newline at end of file diff --git a/tests/7_scheduler/outputs/google_gemini-2.5-pro.js b/tests/7_scheduler/outputs/google_gemini-2.5-pro.js index 1d65edf..47697b8 100644 --- a/tests/7_scheduler/outputs/google_gemini-2.5-pro.js +++ b/tests/7_scheduler/outputs/google_gemini-2.5-pro.js @@ -1,72 +1,58 @@ -const findAvailableSlots = async (calendar1, calendar2, constraints) => { - const [{ default: dayjs }, { default: utc }] = await Promise.all([ - import('https://cdn.skypack.dev/dayjs'), - import('https://cdn.skypack.dev/dayjs/plugin/utc.js'), - ]); - dayjs.extend(utc); +async function findAvailableSlots(calendar1, calendar2, constraints) { + const { + parseISO, addMinutes, formatISO, max, setHours, setMinutes, + setSeconds, setMilliseconds, startOfDay, endOfDay, eachDayOfInterval, + } = await import('https://cdn.jsdelivr.net/npm/date-fns@2/esm/index.js'); - const { durationMinutes, searchRange, workHours } = constraints; - - const toDayjs = (t) => dayjs.utc(t); - const toDayjsRange = ({ start, end }) => ({ start: toDayjs(start), end: toDayjs(end) }); + const { durationMinutes: duration, searchRange, workHours } = constraints; + const searchStart = parseISO(searchRange.start); + const searchEnd = parseISO(searchRange.end); + const [workStartH, workStartM] = workHours.start.split(':').map(Number); + const [workEndH, workEndM] = workHours.end.split(':').map(Number); - const search = toDayjsRange(searchRange); - const allBusy = [...calendar1, ...calendar2] - .map(toDayjsRange) - .sort((a, b) => a.start.valueOf() - b.start.valueOf()); + const setTime = (date, h, m) => + setMilliseconds(setSeconds(setMinutes(setHours(date, h), m), 0), 0); - const mergedBusy = allBusy.reduce((acc, current) => { - const last = acc[acc.length - 1]; - if (last && current.start.valueOf() < last.end.valueOf()) { - if (current.end.isAfter(last.end)) { - last.end = current.end; - } + const busySlots = [...calendar1, ...calendar2].map(({ start, end }) => ({ + start: parseISO(start), + end: parseISO(end), + })); + + const nonWorkSlots = eachDayOfInterval({ start: searchStart, end: searchEnd }) + .flatMap(day => [ + { start: startOfDay(day), end: setTime(day, workStartH, workStartM) }, + { start: setTime(day, workEndH, workEndM), end: endOfDay(day) } + ]); + + const allUnavailable = [...busySlots, ...nonWorkSlots] + .sort((a, b) => a.start - b.start); + + const merged = allUnavailable.reduce((acc, current) => { + const last = acc.at(-1); + if (last && current.start <= last.end) { + last.end = max(last.end, current.end); } else { acc.push({ ...current }); } return acc; }, []); - const boundaryPoints = [ - search.start, - ...mergedBusy.flatMap(b => [b.start, b.end]), - search.end, - ]; - - const freeGaps = []; - for (let i = 0; i < boundaryPoints.length - 1; i += 2) { - const start = boundaryPoints[i]; - const end = boundaryPoints[i + 1]; - if (end.isAfter(start)) { - freeGaps.push({ start, end }); - } - } - const availableSlots = []; - const [workStartH, workStartM] = workHours.start.split(':').map(Number); - const [workEndH, workEndM] = workHours.end.split(':').map(Number); + let cursor = searchStart; - for (const gap of freeGaps) { - let cursor = gap.start.startOf('day'); - while (cursor.isBefore(gap.end)) { - const workWindowStart = cursor.hour(workStartH).minute(workStartM); - const workWindowEnd = cursor.hour(workEndH).minute(workEndM); - - let effectiveStart = dayjs.max(gap.start, workWindowStart); - const effectiveEnd = dayjs.min(gap.end, workWindowEnd); - - while (effectiveStart.add(durationMinutes, 'minute').valueOf() <= effectiveEnd.valueOf()) { - const slotEnd = effectiveStart.add(durationMinutes, 'minute'); - availableSlots.push({ start: effectiveStart, end: slotEnd }); - effectiveStart = slotEnd; - } - cursor = cursor.add(1, 'day'); + [...merged, { start: searchEnd, end: searchEnd }].forEach(block => { + let slotStart = cursor; + while (addMinutes(slotStart, duration) <= block.start) { + const slotEnd = addMinutes(slotStart, duration); + availableSlots.push({ start: slotStart, end: slotEnd }); + slotStart = slotEnd; } - } + cursor = max(cursor, block.end); + }); return availableSlots.map(({ start, end }) => ({ - start: start.toISOString(), - end: end.toISOString(), + start: formatISO(start), + end: formatISO(end), })); -}; +} export default findAvailableSlots; \ No newline at end of file diff --git a/tests/7_scheduler/outputs/google_gemini-3-pro-preview.js b/tests/7_scheduler/outputs/google_gemini-3-pro-preview.js new file mode 100644 index 0000000..18e900c --- /dev/null +++ b/tests/7_scheduler/outputs/google_gemini-3-pro-preview.js @@ -0,0 +1,48 @@ +const findAvailableSlots = async (calA, calB, { durationMinutes: dm, searchRange: sr, workHours: wh }) => { + const { addMinutes } = await import('https://cdn.jsdelivr.net/npm/date-fns@2.30.0/esm/index.js'); + const T = d => new Date(d).getTime(), I = d => new Date(d).toISOString(); + + let busy = [...calA, ...calB] + .map(x => ({ s: T(x.start), e: T(x.end) })) + .sort((a, b) => a.s - b.s) + .reduce((acc, c) => { + const l = acc[acc.length - 1]; + (l && c.s <= l.e) ? l.e = Math.max(l.e, c.e) : acc.push(c); + return acc; + }, []); + + const slots = [], [sh, sm] = wh.start.split(':'), [eh, em] = wh.end.split(':'); + let cur = new Date(sr.start); cur.setHours(0, 0, 0, 0); + + while (T(cur) <= T(sr.end)) { + const wS = new Date(cur); wS.setHours(sh, sm, 0, 0); + const wE = new Date(cur); wE.setHours(eh, em, 0, 0); + const winS = Math.max(T(wS), T(sr.start)), winE = Math.min(T(wE), T(sr.end)); + + if (winS < winE) { + let ptr = winS; + const dBusy = busy.filter(b => b.s < winE && b.e > winS); + + for (const b of dBusy) { + if (ptr < b.s) { + while (T(addMinutes(ptr, dm)) <= b.s) { + const nxt = addMinutes(ptr, dm); + slots.push({ start: I(ptr), end: I(nxt) }); + ptr = T(nxt); + } + } + ptr = Math.max(ptr, b.e); + } + + while (T(addMinutes(ptr, dm)) <= winE) { + const nxt = addMinutes(ptr, dm); + slots.push({ start: I(ptr), end: I(nxt) }); + ptr = T(nxt); + } + } + cur = addMinutes(cur, 1440); + } + + return slots; +}; +export default findAvailableSlots; \ No newline at end of file diff --git a/tests/7_scheduler/outputs/moonshotai_kimi-k2-thinking.js b/tests/7_scheduler/outputs/moonshotai_kimi-k2-thinking.js index faf0f7a..2da2433 100644 --- a/tests/7_scheduler/outputs/moonshotai_kimi-k2-thinking.js +++ b/tests/7_scheduler/outputs/moonshotai_kimi-k2-thinking.js @@ -1,35 +1,57 @@ -export async function findAvailableSlots(a, b, { durationMinutes: d, searchRange: r, workHours: h }) { - const { parseISO, addMinutes, isWithinInterval, compareAsc, startOfDay, setHours, setMinutes } = await import('https://esm.sh/date-fns'); +async function findAvailableSlots(cal1, cal2, constraints) { + const { parseISO, addMinutes, set, max, min, startOfDay } = await import('https://cdn.skypack.dev/date-fns'); - const toDate = (s) => parseISO(s); - const all = [...a, ...b].map(({ start: s, end: e }) => ({ s: toDate(s), e: toDate(e) })); - all.sort((a, b) => compareAsc(a.s, b.s)); + const { durationMinutes, searchRange, workHours } = constraints; + const toDate = d => parseISO(d); + const [whStart, whEnd] = [workHours.start, workHours.end].map(t => t.split(':').map(Number)); + const durMs = durationMinutes * 60000; + const rng = { s: toDate(searchRange.start), e: toDate(searchRange.end) }; - const busy = []; - for (const i of all) { - if (!busy.length || compareAsc(i.s, busy.at(-1).e) > 0) busy.push({ s: i.s, e: i.e }); - else if (compareAsc(i.e, busy.at(-1).e) > 0) busy.at(-1).e = i.e; + const merged = [...cal1, ...cal2] + .map(({ start, end }) => ({ s: toDate(start), e: toDate(end) })) + .sort((a, b) => a.s - b.s) + .reduce((acc, slot) => { + const last = acc.at(-1); + if (!last || slot.s > last.e) acc.push({ ...slot }); + else last.e = max([last.e, slot.e]); + return acc; + }, []); + + const gaps = []; + let cur = rng.s; + for (let i = 0; i <= merged.length; i++) { + const slot = merged[i]; + const end = slot ? slot.s : rng.e; + if (end > cur && cur < rng.e) gaps.push({ s: cur, e: end }); + cur = slot && cur < slot.e ? slot.e : cur; + if (cur >= rng.e) break; } - const range = { s: toDate(r.start), e: toDate(r.end) }; - const [[sh, sm], [eh, em]] = [h.start, h.end].map(t => t.split(':').map(Number)); - const slots = []; - let cur = range.s; - - while (compareAsc(cur, range.e) < 0) { - const end = addMinutes(cur, d); - if (compareAsc(end, range.e) > 0) break; + for (const { s, e } of gaps) { + let day = startOfDay(s); + const lastDay = startOfDay(e); - const day = startOfDay(cur); - const work = { s: setHours(setMinutes(day, sm), sh), e: setHours(setMinutes(day, em), eh) }; - - const inWork = isWithinInterval(cur, work) && isWithinInterval(end, work); - const isFree = !busy.some(b => compareAsc(cur, b.e) < 0 && compareAsc(end, b.s) > 0); - - if (inWork && isFree) slots.push({ start: cur.toISOString(), end: end.toISOString() }); - - cur = end; + while (day <= lastDay) { + const ws = set(day, { hours: whStart[0], minutes: whStart[1], seconds: 0, milliseconds: 0 }); + const we = set(day, { hours: whEnd[0], minutes: whEnd[1], seconds: 0, milliseconds: 0 }); + + if (ws < we) { + const effS = max([ws, s]); + const effE = min([we, e]); + + if (effS < effE) { + let slotS = effS; + while (slotS.getTime() + durMs <= effE.getTime()) { + const slotE = addMinutes(slotS, durationMinutes); + slots.push({ start: slotS.toISOString(), end: slotE.toISOString() }); + slotS = slotE; + } + } + } + + day = addMinutes(day, 1440); + } } return slots; diff --git a/tests/7_scheduler/outputs/openai_gpt-5.1-chat.js b/tests/7_scheduler/outputs/openai_gpt-5.1-chat.js deleted file mode 100644 index de770c6..0000000 --- a/tests/7_scheduler/outputs/openai_gpt-5.1-chat.js +++ /dev/null @@ -1,38 +0,0 @@ -async function findAvailableSlots(a,b,c){ - const f=await import('https://esm.sh/date-fns') - const p=f.parseISO,d=f.addMinutes,x=f.max,y=f.min,i=f.isBefore,j=f.isAfter - const {durationMinutes:r,searchRange:s,workHours:w}=c - const h=t=>t.split(':').map(n=>+n) - const [ws,we]=[h(w.start),h(w.end)] - const z=(d0,[H,M])=>{d0=new Date(d0);d0.setHours(H,M,0,0);return d0.toISOString()} - const S=p(s.start),E=p(s.end) - let u=[...a,...b].map(o=>({start:p(o.start),end:p(o.end)})) - u=u.sort((A,B)=>A.start-B.start) - let m=[] - for(let k of u){ - if(!m.length||k.start>m[m.length-1].end)m.push({start:k.start,end:k.end}) - else m[m.length-1].end=new Date(Math.max(m[m.length-1].end,k.end)) - } - let q=[] - let st=S - for(let k of m){ - if(i(st,k.start)){ - let fs=x(st,S),fe=y(k.start,E) - if(i(fs,fe))q.push({start:fs,end:fe}) - } - st=k.end - } - if(i(st,E))q.push({start:x(st,S),end:E}) - let out=[] - for(let v of q){ - let cs=z(v.start,ws),ce=z(v.start,we) - cs=p(cs);ce=p(ce) - let ss=x(v.start,cs),ee=y(v.end,ce) - for(let t=ss;i(d(t,r),ee)||+d(t,r)==+ee;t=d(t,r)){ - let e=d(t,r) - if(!j(t,ss)||i(e,ee))out.push({start:t.toISOString(),end:e.toISOString()}) - } - } - return out -} -export default findAvailableSlots; \ No newline at end of file diff --git a/tests/7_scheduler/outputs/openai_gpt-5.1-codex.js b/tests/7_scheduler/outputs/openai_gpt-5.1-codex.js index a91ace7..fe9d300 100644 --- a/tests/7_scheduler/outputs/openai_gpt-5.1-codex.js +++ b/tests/7_scheduler/outputs/openai_gpt-5.1-codex.js @@ -1,52 +1,44 @@ -let luxon$ - -const findAvailableSlots = async (calA, calB, cfg) => { - const {DateTime, Interval} = await (luxon$ ||= import('https://cdn.skypack.dev/luxon')) - const {durationMinutes: d, searchRange: r, workHours: w} = cfg - const s = DateTime.fromISO(r.start) - const e = DateTime.fromISO(r.end) - const range = Interval.fromDateTimes(s, e) - const [sh, sm] = w.start.split(':').map(Number) - const [eh, em] = w.end.split(':').map(Number) - const busy = [...calA, ...calB] - .map(({start, end}) => ({start: DateTime.fromISO(start), end: DateTime.fromISO(end)})) - .filter(v => v.end > s && v.start < e) - .map(v => ({start: v.start < s ? s : v.start, end: v.end > e ? e : v.end})) - .sort((a, b) => a.start.valueOf() - b.start.valueOf()) - const merged = [] - for (const slot of busy) { - const last = merged.at(-1) - if (!last || slot.start > last.end) merged.push({...slot}) - else if (slot.end > last.end) last.end = slot.end +async function findAvailableSlots(a,b,c){ + const {DateTime}=await import('https://cdn.skypack.dev/luxon') + const {durationMinutes:d,searchRange:s,workHours:w}=c + const r=[DateTime.fromISO(s.start),DateTime.fromISO(s.end)] + const hm=q=>q.split(':').map(Number) + const [sh,sm]=hm(w.start) + const [eh,em]=hm(w.end) + const clamp=o=>{ + let x=DateTime.fromISO(o.start) + let y=DateTime.fromISO(o.end) + if(+y<=+r[0]||+x>=+r[1])return + if(+x<+r[0])x=r[0] + if(+y>+r[1])y=r[1] + if(+y<=+x)return + return{ s:x,e:y} + } + const merged=[] + ;[...a,...b].map(clamp).filter(Boolean).sort((x,y)=>+x.s-+y.s).forEach(v=>{ + const last=merged.at(-1) + if(!last||+v.s>+last.e)merged.push({s:v.s,e:v.e}) + else if(+v.e>+last.e)last.e=v.e + }) + const gaps=[] + let cur=r[0] + merged.forEach(v=>{ + if(+v.s>+cur)gaps.push({s:cur,e:v.s}) + if(+v.e>+cur)cur=v.e + }) + if(+cur<+r[1])gaps.push({s:cur,e:r[1]}) + const slots=[] + const step={minutes:d} + gaps.forEach(g=>{ + for(let day=g.s.startOf('day');+day<+g.e;day=day.plus({days:1})){ + const ws=day.set({hour:sh,minute:sm,second:0,millisecond:0}) + const we=day.set({hour:eh,minute:em,second:0,millisecond:0}) + let u=+ws>+g.s?ws:g.s + const limit=+we<+g.e?we:g.e + if(+limit<=+u)continue + for(;+u.plus(step)<=+limit;u=u.plus(step))slots.push({start:u.toISO(),end:u.plus(step).toISO()}) } - const out = [] - const emit = (from, to) => { - if (!(to > from)) return - for (let st = from, en = st.plus({minutes: d}); en <= to; st = en, en = st.plus({minutes: d})) - out.push({start: st.toISO(), end: en.toISO()}) - } - let i = 0 - for (let day = s.startOf('day'); day < e; day = day.plus({days: 1})) { - const ws = day.set({hour: sh, minute: sm, second: 0, millisecond: 0}) - const we = day.set({hour: eh, minute: em, second: 0, millisecond: 0}) - const block = Interval.fromDateTimes(ws, we).intersection(range) - if (!block) continue - while (i < merged.length && merged[i].end <= block.start) i++ - let cursor = block.start - for (let j = i; j < merged.length && merged[j].start < block.end; j++) { - const bs = merged[j].start > block.start ? merged[j].start : block.start - if (bs > cursor) { - emit(cursor, bs) - cursor = bs - } - if (merged[j].end > cursor) { - const be = merged[j].end < block.end ? merged[j].end : block.end - cursor = be - } - if (cursor >= block.end) break - } - if (cursor < block.end) emit(cursor, block.end) - } - return out + }) + return slots } export default findAvailableSlots; \ No newline at end of file diff --git a/tests/7_scheduler/outputs/openrouter_sherlock-dash-alpha.js b/tests/7_scheduler/outputs/openrouter_sherlock-dash-alpha.js deleted file mode 100644 index a3fb81e..0000000 --- a/tests/7_scheduler/outputs/openrouter_sherlock-dash-alpha.js +++ /dev/null @@ -1,67 +0,0 @@ -async function findAvailableSlots(cal1, cal2, {durationMinutes, searchRange, workHours}) { - const {luxon: {DateTime, Interval}} = await import('https://cdn.skypack.dev/luxon'); - - const workStart = DateTime.fromFormat(workHours.start, 'HH:mm'); - const workEnd = DateTime.fromFormat(workHours.end, 'HH:mm'); - const searchStart = DateTime.fromISO(searchRange.start); - const searchEnd = DateTime.fromISO(searchRange.end); - const duration = Duration.fromObject({minutes: durationMinutes}); - - const parseCal = cal => cal.map(s => ({ - start: DateTime.fromISO(s.start), - end: DateTime.fromISO(s.end) - })).filter(s => s.start < s.end); - - const mergeOverlaps = slots => slots - .sort((a,b) => a.start - b.end) - .reduce((merged, curr) => { - const last = merged[merged.length - 1]; - if (!last || last.end < curr.start) return [...merged, curr]; - last.end = Math.max(last.end, curr.end); - return merged; - }, []); - - const allBusy = mergeOverlaps([...parseCal(cal1), ...parseCal(cal2)]); - const freePeriods = [ - {start: searchStart, end: allBusy[0]?.start || searchEnd}, - ...allBusy.flatMap((b,i) => - i < allBusy.length - 1 && b.end < allBusy[i+1].start - ? [{start: b.end, end: allBusy[i+1].start}] - : [] - ), - ...(allBusy.at(-1)?.end && allBusy.at(-1).end < searchEnd - ? [{start: allBusy.at(-1).end, end: searchEnd}] - : []) - ].filter(p => p.start < p.end); - - const slots = []; - for (const period of freePeriods) { - const int = Interval.fromDateTimes(period.start, period.end); - let curr = int.start; - - while (curr.plus(duration) <= int.end) { - const slotStart = curr; - const slotEnd = curr.plus(duration); - - const dayStart = slotStart.set({hour: workStart.hour, minute: workStart.minute, second: 0, millisecond: 0}); - const dayEnd = slotStart.set({hour: workEnd.hour, minute: workEnd.minute, second: 0, millisecond: 0}); - - if (Interval.fromDateTimes(slotStart, slotEnd).containedBy( - Interval.fromDateTimes( - Math.max(slotStart, dayStart), - Math.min(slotEnd, dayEnd) - ) - )) { - slots.push({ - start: slotStart.toISO(), - end: slotEnd.toISO() - }); - } - - curr = slotEnd; - } - } - - return slots; -} -export default findAvailableSlots; \ No newline at end of file diff --git a/tests/7_scheduler/outputs/openrouter_sherlock-think-alpha.js b/tests/7_scheduler/outputs/openrouter_sherlock-think-alpha.js index b07ed8b..8c736fb 100644 --- a/tests/7_scheduler/outputs/openrouter_sherlock-think-alpha.js +++ b/tests/7_scheduler/outputs/openrouter_sherlock-think-alpha.js @@ -1,77 +1,71 @@ -async function findAvailableSlots(cal1, cal2, constraints) { - const { DateTime, Interval } = await import('https://cdn.skypack.dev/luxon'); - const { durationMinutes, searchRange, workHours } = constraints; - const searchStart = DateTime.fromISO(searchRange.start); - const searchEnd = DateTime.fromISO(searchRange.end); - const searchInterval = Interval.fromDateTimes(searchStart, searchEnd); - const zone = searchStart.zone; - const workStart = DateTime.fromFormat(workHours.start, 'HH:mm', { zone }); - const workEnd = DateTime.fromFormat(workHours.end, 'HH:mm', { zone }); - let busies = []; - for (const slot of [...cal1, ...cal2]) { - const iv = Interval.fromISO(`${slot.start}/${slot.end}`); - const i = iv.intersection(searchInterval); - if (i?.isValid) busies.push(i); - } - let nonWork = []; - let currentDay = searchStart.startOf('day'); - const endDay = searchEnd.endOf('day'); - while (currentDay <= endDay) { - const dayStart = currentDay; - const dayEnd = currentDay.plus({ days: 1 }); - const wStart = dayStart.set({ hour: workStart.hour, minute: workStart.minute, second: 0, millisecond: 0 }); - const wEnd = dayStart.set({ hour: workEnd.hour, minute: workEnd.minute, second: 0, millisecond: 0 }); - const blocks = []; - if (dayStart < wStart) blocks.push(Interval.fromDateTimes(dayStart, wStart)); - if (wEnd < dayEnd) blocks.push(Interval.fromDateTimes(wEnd, dayEnd)); - for (const b of blocks) { - const i = b.intersection(searchInterval); - if (i?.isValid) nonWork.push(i); +async function findAvailableSlots(cal1, cal2, cons) { + const { DateTime: DT, Interval: IV, Duration: D } = await import('https://esm.sh/luxon@3.4.4'); + const dur = D.fromObject({ minutes: cons.durationMinutes }); + const sr = IV.fromISO(`${cons.searchRange.start}/${cons.searchRange.end}`); + const [h1, m1] = cons.workHours.start.split(':').map(Number); + const [h2, m2] = cons.workHours.end.split(':').map(Number); + let busies = [...cal1, ...cal2].map(e => IV.fromISO(`${e.start}/${e.end}`)) + .filter(iv => iv?.overlaps(sr)) + .map(iv => iv.intersection(sr)) + .filter(iv => iv && !iv.isEmpty) + .sort((a, b) => a.start.toMillis() - b.start.toMillis()); + let merged = []; + for (let iv of busies) { + if (!merged.length) { + merged.push(iv); + continue; } - currentDay = currentDay.plus({ days: 1 }); - } - let allBlocked = [...busies, ...nonWork].sort((a, b) => a.start.valueOf() - b.start.valueOf()); - const mergedBlocked = []; - for (const iv of allBlocked) { - const last = mergedBlocked.at(-1); - if (!last || !last.overlaps(iv)) { - mergedBlocked.push(iv); + let last = merged[merged.length - 1]; + if (last.end >= iv.start) { + const newEnd = last.end.toMillis() > iv.end.toMillis() ? last.end : iv.end; + merged[merged.length - 1] = IV.fromDateTimes(last.start, newEnd); } else { - mergedBlocked[mergedBlocked.length - 1] = last.union(iv); + merged.push(iv); } } - const freePeriods = []; - if (mergedBlocked.length === 0) { - freePeriods.push(searchInterval); - } else { - if (searchStart < mergedBlocked[0].start) { - freePeriods.push(Interval.fromDateTimes(searchStart, mergedBlocked[0].start)); + let frees = []; + let prevEnd = sr.start; + for (let busy of merged) { + if (prevEnd < busy.start) { + frees.push(IV.fromDateTimes(prevEnd, busy.start)); } - for (let i = 0; i < mergedBlocked.length - 1; i++) { - const gapStart = mergedBlocked[i].end; - const gapEnd = mergedBlocked[i + 1].start; - if (gapStart < gapEnd) { - freePeriods.push(Interval.fromDateTimes(gapStart, gapEnd)); + prevEnd = busy.end; + } + if (prevEnd < sr.end) { + frees.push(IV.fromDateTimes(prevEnd, sr.end)); + } + let workFrees = []; + for (let free of frees) { + let cur = free.start; + while (cur < free.end) { + let dayS = cur.startOf('day'); + let dayE = dayS.plus({ days: 1 }); + let dInt = IV.fromDateTimes(dayS, dayE); + let dayFree = free.intersection(dInt); + if (dayFree && !dayFree.isEmpty) { + let wS = dayS.plus({ hours: h1, minutes: m1 }); + let wE = dayS.plus({ hours: h2, minutes: m2 }); + let wInt = IV.fromDateTimes(wS, wE); + let wf = dayFree.intersection(wInt); + if (wf && !wf.isEmpty) { + workFrees.push(wf); + } } - } - if (mergedBlocked.at(-1).end < searchEnd) { - freePeriods.push(Interval.fromDateTimes(mergedBlocked.at(-1).end, searchEnd)); + cur = dayE; } } - const availableSlots = []; - for (const freeIv of freePeriods) { - if (freeIv.length('milliseconds') < durationMinutes * 60 * 1000) continue; - let current = freeIv.start; - while (true) { - const slotEnd = current.plus({ minutes: durationMinutes }); - if (slotEnd > freeIv.end) break; - availableSlots.push({ - start: current.toISO(), - end: slotEnd.toISO() - }); - current = slotEnd; + let slots = []; + const dMs = dur.toMillis(); + for (let wf of workFrees) { + let remMs = wf.end.toMillis() - wf.start.toMillis(); + let n = Math.floor(remMs / dMs); + let fs = wf.start; + for (let i = 0; i < n; i++) { + let ss = fs.plus(D.fromMillis(i * dMs)); + let se = ss.plus(dur); + slots.push({ start: ss.toISO(), end: se.toISO() }); } } - return availableSlots; + return slots; } export default findAvailableSlots; \ No newline at end of file diff --git a/tests/8_json_validator/outputs/anthropic_claude-sonnet-4.5 TEMP_0.7.js b/tests/8_json_validator/outputs/anthropic_claude-sonnet-4.5 TEMP_0.7.js index 27b11b6..5fbf094 100644 --- a/tests/8_json_validator/outputs/anthropic_claude-sonnet-4.5 TEMP_0.7.js +++ b/tests/8_json_validator/outputs/anthropic_claude-sonnet-4.5 TEMP_0.7.js @@ -6,12 +6,9 @@ const validateJSON = async (data, schema) => { return { valid, - errors: valid ? [] : validate.errors.map(e => ({ - path: e.instancePath || '/', - message: e.message, - keyword: e.keyword, - params: e.params - })) + errors: valid ? [] : validate.errors.map(e => + `${e.instancePath || '/'} ${e.message}`.trim() + ) }; }; export default validateJSON; \ No newline at end of file diff --git a/tests/8_json_validator/outputs/google_gemini-2.5-pro.js b/tests/8_json_validator/outputs/google_gemini-2.5-pro.js index 5c85970..15979b8 100644 --- a/tests/8_json_validator/outputs/google_gemini-2.5-pro.js +++ b/tests/8_json_validator/outputs/google_gemini-2.5-pro.js @@ -1,17 +1,16 @@ const validateJSON = async (data, schema) => { - try { - const { default: Ajv } = await import('https://esm.sh/ajv@8'); - const validate = new Ajv({ allErrors: true }).compile(schema); - const valid = validate(data); + const { default: Ajv } = await import('https://esm.sh/ajv@8'); - return { - valid, - errors: valid ? [] : (validate.errors ?? []).map( - ({ instancePath, message }) => `${instancePath || 'root'} ${message}`.trim() - ), - }; - } catch (e) { - return { valid: false, errors: [e.message] }; - } + const ajv = new Ajv({ allErrors: true }); + const validate = ajv.compile(schema); + const valid = validate(data); + + const errors = valid + ? [] + : validate.errors.map( + ({ instancePath, message }) => `${instancePath || 'object'} ${message}`.trim() + ); + + return { valid, errors }; }; export default validateJSON; \ No newline at end of file diff --git a/tests/8_json_validator/outputs/google_gemini-3-pro-preview.js b/tests/8_json_validator/outputs/google_gemini-3-pro-preview.js new file mode 100644 index 0000000..de2e0ca --- /dev/null +++ b/tests/8_json_validator/outputs/google_gemini-3-pro-preview.js @@ -0,0 +1,14 @@ +const validateJSON = async (data, schema) => { + const { default: Ajv } = await import('https://esm.sh/ajv@8.17.1') + const ajv = new Ajv({ allErrors: true }) + const validate = ajv.compile(schema) + const valid = validate(data) + + return { + valid, + errors: valid ? [] : validate.errors.map(({ instancePath, message }) => + `${instancePath} ${message}`.trim() + ) + } +} +export default validateJSON; \ No newline at end of file diff --git a/tests/8_json_validator/outputs/moonshotai_kimi-k2-thinking.js b/tests/8_json_validator/outputs/moonshotai_kimi-k2-thinking.js index 64b8c47..b514ba6 100644 --- a/tests/8_json_validator/outputs/moonshotai_kimi-k2-thinking.js +++ b/tests/8_json_validator/outputs/moonshotai_kimi-k2-thinking.js @@ -1,17 +1,25 @@ -const cache = new WeakMap(); -let ajv; - -async function validateJSON(json, schema) { +const validateJSON = async (data, schema) => { try { - if (!ajv) { - const { default: Ajv } = await import('https://cdn.jsdelivr.net/npm/ajv@8/dist/ajv.mjs'); - ajv = new Ajv({ allErrors: true, strict: false }); - } - const validator = cache.get(schema) || (cache.set(schema, ajv.compile(schema)), cache.get(schema)); - const valid = validator(json); - return { valid, errors: valid ? [] : validator.errors.map(e => `${e.instancePath} ${e.message}`.trim()) }; - } catch (error) { - return { valid: false, errors: [error.message] }; + const { default: Ajv } = await import('https://esm.sh/ajv@8.12.0'); + const ajv = new Ajv({ allErrors: true, strict: false }); + try { + const { default: addFormats } = await import('https://esm.sh/ajv-formats@2.1.1'); + addFormats(ajv); + } catch {} + + const validate = ajv.compile(schema); + const valid = validate(data); + + return { + valid, + errors: valid ? [] : validate.errors.map(e => { + const path = (e.instancePath || 'root') + (e.keyword === 'required' ? `.${e.params.missingProperty}` : ''); + const pattern = e.params?.pattern ? ` (${e.params.pattern})` : ''; + return `${path} ${e.message}${pattern}`.trim(); + }) + }; + } catch (e) { + return { valid: false, errors: [`Validator error: ${e.message}`] }; } -} +}; export default validateJSON; \ No newline at end of file diff --git a/tests/8_json_validator/outputs/openai_gpt-5.1-chat.js b/tests/8_json_validator/outputs/openai_gpt-5.1-chat.js deleted file mode 100644 index 762d50b..0000000 --- a/tests/8_json_validator/outputs/openai_gpt-5.1-chat.js +++ /dev/null @@ -1,8 +0,0 @@ -async function validateJSON(d,s){ - const {default:Ajv}=await import('https://cdn.skypack.dev/ajv'); - const a=new Ajv({allErrors:true}); - const v=a.compile(s); - const ok=v(d); - return{valid:ok,errors:ok?[]:(v.errors||[]).map(e=>e.message||'')}; -} -export default validateJSON; \ No newline at end of file diff --git a/tests/8_json_validator/outputs/openai_gpt-5.1-codex.js b/tests/8_json_validator/outputs/openai_gpt-5.1-codex.js index ccd2b93..893fc32 100644 --- a/tests/8_json_validator/outputs/openai_gpt-5.1-codex.js +++ b/tests/8_json_validator/outputs/openai_gpt-5.1-codex.js @@ -1,9 +1,9 @@ -export async function validateJSON(data, schema) { - const { default: Ajv } = await import('https://esm.sh/ajv@8?bundle'); - const ajv = new Ajv({ allErrors: true, strict: false }); - const validate = ajv.compile(schema); - const valid = validate(data); - const errors = valid ? [] : (validate.errors || []).map(e => `${e.instancePath || '/'} ${e.message || ''}`.trim()); - return { valid, errors }; +const fetchAjv=(()=>{let p;return()=>p??=import('https://cdn.jsdelivr.net/npm/ajv@8/dist/ajv.min.js?module').then(({default:A})=>new A({allErrors:true,strict:false}));})(); + +async function validateJSON(data,schema){ + const ajv=await fetchAjv(); + const validate=ajv.compile(schema); + const valid=validate(data); + return {valid,errors:valid?[]:validate.errors.map(e=>e.message||'Invalid')}; } export default validateJSON; \ No newline at end of file diff --git a/tests/8_json_validator/outputs/openrouter_sherlock-dash-alpha.js b/tests/8_json_validator/outputs/openrouter_sherlock-dash-alpha.js deleted file mode 100644 index c9a005d..0000000 --- a/tests/8_json_validator/outputs/openrouter_sherlock-dash-alpha.js +++ /dev/null @@ -1,13 +0,0 @@ -async function validateJSON(data, schema) { - const { default: Ajv } = await import('https://cdn.skypack.dev/ajv@8'); - const ajv = new Ajv({ allErrors: true, verbose: true }); - const validate = ajv.compile(schema); - const valid = validate(data); - return { - valid, - errors: valid ? [] : ajv.errors?.map(e => - `${e.instancePath || 'data'}: ${e.message} (${e.params?.type || e.schema})` - ) || [] - }; -} -export default validateJSON; \ No newline at end of file diff --git a/tests/8_json_validator/outputs/openrouter_sherlock-think-alpha.js b/tests/8_json_validator/outputs/openrouter_sherlock-think-alpha.js index 4dea5cb..7c4c595 100644 --- a/tests/8_json_validator/outputs/openrouter_sherlock-think-alpha.js +++ b/tests/8_json_validator/outputs/openrouter_sherlock-think-alpha.js @@ -1,20 +1,11 @@ -const getAjv = async () => { - if (!getAjv.instance) { - const { default: Ajv } = await import('https://cdn.skypack.dev/ajv@8'); - getAjv.instance = new Ajv({ allErrors: true }); - } - return getAjv.instance; -}; - -const validateJSON = async (data, schema) => { - try { - const ajv = await getAjv(); - const validate = ajv.compile(schema); - const valid = validate(data); - const errors = valid ? [] : ajv.errorsText(ajv.errors, { separator: '\n' }).split('\n').filter(s => s.trim()); - return { valid, errors }; - } catch (e) { - return { valid: false, errors: [`Validation error: ${e.message}`] }; - } -}; +async function validateJSON(data, schema) { + const { default: Ajv } = await import('https://esm.sh/ajv@8'); + const ajv = new Ajv({ allErrors: true }); + const validate = ajv.compile(schema); + const valid = validate(data); + return { + valid, + errors: valid ? [] : validate.errors.map(e => e.message) + }; +} export default validateJSON; \ No newline at end of file diff --git a/tests/9_stream_visualizer/outputs/anthropic_claude-sonnet-4.5 TEMP_0.7.js b/tests/9_stream_visualizer/outputs/anthropic_claude-sonnet-4.5 TEMP_0.7.js index afd30db..5782dd1 100644 --- a/tests/9_stream_visualizer/outputs/anthropic_claude-sonnet-4.5 TEMP_0.7.js +++ b/tests/9_stream_visualizer/outputs/anthropic_claude-sonnet-4.5 TEMP_0.7.js @@ -6,9 +6,14 @@ export async function createStreamVisualizer(asyncIterable, options) { let prevEma; for await (const { timestamp, value } of asyncIterable) { - const ema = prevEma === undefined ? value : alpha * value + (1 - alpha) * prevEma; + const ema = prevEma === undefined + ? value + : alpha * value + (1 - alpha) * prevEma; + data.push({ timestamp, value, ema }); + if (data.length > maxPoints) data.shift(); + prevEma = ema; } diff --git a/tests/9_stream_visualizer/outputs/google_gemini-2.5-pro.js b/tests/9_stream_visualizer/outputs/google_gemini-2.5-pro.js index 7d2c34d..fda4184 100644 --- a/tests/9_stream_visualizer/outputs/google_gemini-2.5-pro.js +++ b/tests/9_stream_visualizer/outputs/google_gemini-2.5-pro.js @@ -11,42 +11,32 @@ async function createStreamVisualizer(asyncIterable, { } = await import('d3'); const data = []; - let prevEma = null; + let prevEma; - for await (const { - timestamp, - value - } of asyncIterable) { - const ema = prevEma === null ? + for await (const { value, timestamp } of asyncIterable) { + prevEma = (prevEma === undefined) ? value : alpha * value + (1 - alpha) * prevEma; data.push({ timestamp, value, - ema + ema: prevEma }); - prevEma = ema; - if (data.length > maxPoints) { data.shift(); } } - if (data.length < 2) { + if (!data.length) { return { data, path: '' }; } - const x = scaleLinear() - .domain([data[0].timestamp, data.at(-1).timestamp]) - .range([0, width]); - - const y = scaleLinear() - .domain(yDomain) - .range([height, 0]); + const x = scaleLinear([data[0].timestamp, data.at(-1).timestamp], [0, width]); + const y = scaleLinear(yDomain, [height, 0]); const path = line() .x(d => x(d.timestamp)) @@ -54,7 +44,7 @@ async function createStreamVisualizer(asyncIterable, { return { data, - path + path: path ?? '' }; } export default createStreamVisualizer; \ No newline at end of file diff --git a/tests/9_stream_visualizer/outputs/google_gemini-3-pro-preview.js b/tests/9_stream_visualizer/outputs/google_gemini-3-pro-preview.js new file mode 100644 index 0000000..5d57763 --- /dev/null +++ b/tests/9_stream_visualizer/outputs/google_gemini-3-pro-preview.js @@ -0,0 +1,32 @@ +export const createStreamVisualizer = async ( + stream, + { maxPoints, alpha, width, height, yDomain } +) => { + const { scaleLinear, line } = await import('https://cdn.jsdelivr.net/npm/d3@7/+esm'); + const data = []; + let prev = null; + + for await (const { timestamp, value } of stream) { + const ema = prev == null ? value : alpha * value + (1 - alpha) * prev; + prev = ema; + data.push({ timestamp, value, ema }); + if (data.length > maxPoints) data.shift(); + } + + if (!data.length) return { data, path: '' }; + + const x = scaleLinear() + .domain([data[0].timestamp, data[data.length - 1].timestamp]) + .range([0, width]); + + const y = scaleLinear() + .domain(yDomain) + .range([height, 0]); + + const curve = line() + .x(d => x(d.timestamp)) + .y(d => y(d.ema)); + + return { data, path: curve(data) }; +}; +export default createStreamVisualizer; \ No newline at end of file diff --git a/tests/9_stream_visualizer/outputs/moonshotai_kimi-k2-thinking.js b/tests/9_stream_visualizer/outputs/moonshotai_kimi-k2-thinking.js index df51844..166cb31 100644 --- a/tests/9_stream_visualizer/outputs/moonshotai_kimi-k2-thinking.js +++ b/tests/9_stream_visualizer/outputs/moonshotai_kimi-k2-thinking.js @@ -1,9 +1,68 @@ -export async function createStreamVisualizer(i,o){ - const d=await import('d3'),{maxPoints:m,alpha:a,width:w,height:h,yDomain:y}=o,p=[],c=d.scaleLinear,f=d.line; - let e; - for await(const{timestamp:t,value:v}of i){e=e===undefined?v:a*v+(1-a)*e;p.push({timestamp:t,value:v,ema:e});p.length>m&&p.shift()} - if(!p.length)return{data:[],path:''}; - const x=c().domain([p[0].timestamp,p.at(-1).timestamp]).range([0,w]),z=c().domain(y).range([h,0]),g=f().x(d=>x(d.timestamp)).y(d=>z(d.ema)).curve(d.curveLinear); - return{data:p,path:g(p)} +async function createStreamVisualizer(asyncIterable, options) { + const { maxPoints, alpha, width, height, yDomain } = options; + const d3 = await import('https://cdn.jsdelivr.net/npm/d3@7/+esm'); + + if (!Number.isFinite(maxPoints) || maxPoints < 1) { + throw new Error('maxPoints must be a positive integer'); + } + if (!Number.isFinite(alpha) || alpha < 0 || alpha > 1) { + throw new Error('alpha must be between 0 and 1'); + } + if (!Array.isArray(yDomain) || yDomain.length !== 2) { + throw new Error('yDomain must be an array of [min, max]'); + } + if (!Number.isFinite(width) || width <= 0) { + throw new Error('width must be a positive number'); + } + if (!Number.isFinite(height) || height <= 0) { + throw new Error('height must be a positive number'); + } + + const data = []; + let prevEma = null; + let itemCount = 0; + + for await (const value of asyncIterable) { + if (!Number.isFinite(value)) { + throw new Error('Stream must yield finite numeric values'); + } + + const timestamp = Date.now(); + const ema = prevEma === null ? value : alpha * value + (1 - alpha) * prevEma; + const point = { timestamp, value, ema }; + + if (itemCount < maxPoints) { + data.push(point); + itemCount++; + } else { + data.shift(); + data.push(point); + } + + prevEma = ema; + } + + let path = ''; + if (data.length > 0) { + const xDomain = data.length > 1 ? [data[0].timestamp, data[data.length - 1].timestamp] : [data[0].timestamp - 1000, data[0].timestamp]; + + const xScale = d3.scaleLinear() + .domain(xDomain) + .range([0, width]); + + const yScale = d3.scaleLinear() + .domain(yDomain) + .range([height, 0]); + + const line = d3.line() + .x(d => xScale(d.timestamp)) + .y(d => yScale(d.ema)) + .curve(d3.curveMonotoneX) + .defined(d => Number.isFinite(d.ema)); + + path = line(data) || ''; + } + + return { data, path }; } export default createStreamVisualizer; \ No newline at end of file diff --git a/tests/9_stream_visualizer/outputs/openai_gpt-5.1-chat.js b/tests/9_stream_visualizer/outputs/openai_gpt-5.1-chat.js deleted file mode 100644 index a8e6957..0000000 --- a/tests/9_stream_visualizer/outputs/openai_gpt-5.1-chat.js +++ /dev/null @@ -1,23 +0,0 @@ -export async function createStreamVisualizer(iter, o) { - const { maxPoints, alpha, width, height, yDomain } = o - const d3 = await import('https://cdn.jsdelivr.net/npm/d3@7/+esm') - const data = [] - let ema - for await (const { timestamp, value } of iter) { - ema = ema == null ? value : alpha * value + (1 - alpha) * ema - data.push({ timestamp, value, ema }) - if (data.length > maxPoints) data.shift() - } - const xs = d3.scaleLinear() - .domain([data[0].timestamp, data[data.length - 1].timestamp]) - .range([0, width]) - const ys = d3.scaleLinear() - .domain(yDomain) - .range([height, 0]) - const line = d3.line() - .x(d => xs(d.timestamp)) - .y(d => ys(d.ema)) - const path = line(data) || '' - return { data, path } -} -export default createStreamVisualizer; \ No newline at end of file diff --git a/tests/9_stream_visualizer/outputs/openai_gpt-5.1-codex.js b/tests/9_stream_visualizer/outputs/openai_gpt-5.1-codex.js index f33d3b1..1d4e637 100644 --- a/tests/9_stream_visualizer/outputs/openai_gpt-5.1-codex.js +++ b/tests/9_stream_visualizer/outputs/openai_gpt-5.1-codex.js @@ -1,23 +1,18 @@ -async function createStreamVisualizer(iterable, { - maxPoints = 100, - alpha = .5, - width = 300, - height = 150, - yDomain = [0, 1] -} = {}) { - const { scaleLinear, line } = await import('https://cdn.jsdelivr.net/npm/d3@7/+esm') - const data = [] +const createStreamVisualizer=async(iter,o)=>{ + const{maxPoints:m,alpha:a,width:w,height:h,yDomain:Y}=o + const data=[] let ema - for await (const point of iterable) { - const { timestamp, value } = point - ema = ema == null ? value : alpha * value + (1 - alpha) * ema - data.push({ timestamp, value, ema }) - data.length > maxPoints && data.shift() + for await(const {timestamp:t,value:v} of iter){ + const d=new Date(t) + ema=ema==null?v:a*v+(1-a)*ema + data.push({timestamp:d,value:v,ema}) + if(data.length>m)data.shift() } - if (!data.length) return { data, path: '' } - const x = scaleLinear().domain([data[0].timestamp, data.at(-1).timestamp]).range([0, width]) - const y = scaleLinear().domain(yDomain).range([height, 0]) - const path = line().x(d => x(d.timestamp)).y(d => y(d.ema))(data) || '' - return { data, path } + if(!data.length)return{data,path:''} + const{scaleTime,scaleLinear,line}=await import('https://cdn.skypack.dev/d3@7?min') + const x=scaleTime().domain([data[0].timestamp,data[data.length-1].timestamp]).range([0,w]) + const y=scaleLinear().domain(Y).range([h,0]) + const path=line().x(d=>x(d.timestamp)).y(d=>y(d.ema))(data)||'' + return{data,path} } export default createStreamVisualizer; \ No newline at end of file diff --git a/tests/9_stream_visualizer/outputs/openrouter_sherlock-dash-alpha.js b/tests/9_stream_visualizer/outputs/openrouter_sherlock-dash-alpha.js deleted file mode 100644 index 4966fd1..0000000 --- a/tests/9_stream_visualizer/outputs/openrouter_sherlock-dash-alpha.js +++ /dev/null @@ -1,26 +0,0 @@ -async function createStreamVisualizer(asyncIterable, { maxPoints = 100, alpha = 0.3, width = 800, height = 400, yDomain = [-1, 1] } = {}) { - const { select, scaleLinear, scaleTime, line } = await import('https://cdn.skypack.dev/d3@7'); - - let data = [], prevEma; - - for await (const { timestamp, value } of asyncIterable) { - const ema = prevEma === undefined ? value : alpha * value + (1 - alpha) * prevEma; - prevEma = ema; - - data.push({ timestamp, value, ema }); - if (data.length > maxPoints) data.shift(); - } - - if (!data.length) return { data: [], path: '' }; - - const x = scaleLinear().domain([data[0].timestamp, data[data.length - 1].timestamp]).range([0, width]); - const y = scaleLinear().domain(yDomain).range([height, 0]); - - const lineGen = line() - .x(d => x(d.timestamp)) - .y(d => y(d.ema)) - .curve(select.curveMonotoneX); - - return { data, path: lineGen(data) }; -} -export default createStreamVisualizer; \ No newline at end of file diff --git a/tests/9_stream_visualizer/outputs/openrouter_sherlock-think-alpha.js b/tests/9_stream_visualizer/outputs/openrouter_sherlock-think-alpha.js index 0865c03..424e422 100644 --- a/tests/9_stream_visualizer/outputs/openrouter_sherlock-think-alpha.js +++ b/tests/9_stream_visualizer/outputs/openrouter_sherlock-think-alpha.js @@ -1,16 +1,19 @@ -async function createStreamVisualizer(iter,opts){ - const{maxPoints:max,alpha,width,height,yDomain}=opts; - let data=[],prev=null; - for await(const i of iter){ - const ts=i.timestamp,v=i.value,e=prev==null?v:alpha*v+(1-alpha)*prev; - prev=e; - data.push({timestamp:ts,value:v,ema:e}); - if(data.length>max)data.shift(); +async function createStreamVisualizer(asyncIterable,options){ + const{maxPoints,alpha,width,height,yDomain}=options; + const{scaleLinear:sl,line}=await import('https://cdn.skypack.dev/d3'); + let points=[]; + let prevEma=NaN; + for await(const{timestamp,value}of asyncIterable){ + const ema=isNaN(prevEma)?value:alpha*value+(1-alpha)*prevEma; + points.push({timestamp,value,ema}); + prevEma=ema; + if(points.length>maxPoints)points.shift(); } - const{scaleLinear,line}=await import('https://cdn.skypack.dev/d3'); - if(!data.length)return{data,path:''}; - const x=scaleLinear().domain([data[0].timestamp,data.at(-1).timestamp]).range([0,width]); - const y=scaleLinear().domain(yDomain).range([height,0]); - return{data,line().x(d=>x(d.timestamp)).y(d=>y(d.ema))(data)}; + if(!points.length)return{data:[],path:''}; + const xDomain=[points[0].timestamp,points[points.length-1].timestamp]; + const x=sl().domain(xDomain).range([0,width]); + const y=sl().domain(yDomain).range([height,0]); + const lineGen=line().x(d=>x(d.timestamp)).y(d=>y(d.ema)); + return{data:points,path:lineGen(points)}; } export default createStreamVisualizer; \ No newline at end of file