mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-08-26 04:57:08 -05:00
Make searching orgs, weapons less fussy
This commit is contained in:
@@ -37,6 +37,15 @@ sql.pragma("mmap_size = 3221225472");
|
||||
// connections; pair with a periodic `PRAGMA optimize;` (see OptimizeDatabase routine)
|
||||
sql.pragma("optimize = 0x10002");
|
||||
|
||||
// Strips diacritics so accent-insensitive name searches are possible
|
||||
// (e.g. "cafe" matches "Café"). Combined with LIKE's built-in ASCII
|
||||
// case-insensitivity this also folds case for the resulting latin letters.
|
||||
sql.function("unaccent", { deterministic: true }, (value) =>
|
||||
typeof value === "string"
|
||||
? value.normalize("NFD").replace(/\p{M}/gu, "")
|
||||
: value,
|
||||
);
|
||||
|
||||
export const db = new Kysely<DB>({
|
||||
dialect: new SqliteDialect({
|
||||
database: sql,
|
||||
|
||||
@@ -200,7 +200,13 @@ export function searchByName({
|
||||
"avatarUrl",
|
||||
),
|
||||
])
|
||||
.where("TournamentOrganization.name", "like", `%${query}%`)
|
||||
.where(({ eb, ref }) =>
|
||||
eb(
|
||||
sql`unaccent(${ref("TournamentOrganization.name")})`,
|
||||
"like",
|
||||
sql`unaccent(${`%${query}%`})`,
|
||||
),
|
||||
)
|
||||
.orderBy("TournamentOrganization.name", "asc")
|
||||
.limit(limit)
|
||||
.execute();
|
||||
|
||||
47
app/modules/in-game-lists/utils.test.ts
Normal file
47
app/modules/in-game-lists/utils.test.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
import { describe, expect, test } from "vitest";
|
||||
import type { MainWeaponId } from "./types";
|
||||
import { filterWeapon } from "./utils";
|
||||
|
||||
describe("filterWeapon", () => {
|
||||
const sBlast = { type: "MAIN" as const, id: 260 as MainWeaponId };
|
||||
|
||||
test("matches ignoring hyphens (e.g. 's blast' finds 'S-BLAST')", () => {
|
||||
expect(
|
||||
filterWeapon({
|
||||
weapon: sBlast,
|
||||
weaponName: "S-BLAST '92",
|
||||
searchTerm: "s blast",
|
||||
}),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
test("matches with the hyphen still present", () => {
|
||||
expect(
|
||||
filterWeapon({
|
||||
weapon: sBlast,
|
||||
weaponName: "S-BLAST '92",
|
||||
searchTerm: "s-blast",
|
||||
}),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
test("matches ignoring case", () => {
|
||||
expect(
|
||||
filterWeapon({
|
||||
weapon: sBlast,
|
||||
weaponName: "S-BLAST '92",
|
||||
searchTerm: "SBLAST",
|
||||
}),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
test("does not match unrelated weapon", () => {
|
||||
expect(
|
||||
filterWeapon({
|
||||
weapon: sBlast,
|
||||
weaponName: "S-BLAST '92",
|
||||
searchTerm: "splattershot",
|
||||
}),
|
||||
).toBe(false);
|
||||
});
|
||||
});
|
||||
@@ -8,7 +8,11 @@ export function isAbility(value: string): value is Ability {
|
||||
}
|
||||
|
||||
const normalizeTerm = (term: string): string => {
|
||||
return term.trim().toLocaleLowerCase();
|
||||
return term
|
||||
.normalize("NFD")
|
||||
.replace(/\p{M}/gu, "")
|
||||
.replace(/[^\p{L}\p{N}]/gu, "")
|
||||
.toLocaleLowerCase();
|
||||
};
|
||||
|
||||
export function filterWeapon({
|
||||
|
||||
Reference in New Issue
Block a user