Open14
単価計算アプリを Svelte で作ってみる
Twitter でステップを記録したけど、TL の趣味関心とは遠いので、ここで更新することにした
Twitter で更新したもの
言い忘れたけど、削除ボタンを綺麗にしたうえで hover と focus 状態の style を追加した
そして sanitize.css を使うようになった(なんか便利)
まだ調節が必要だけど
タイトルを編輯できるようになった
数式も使えるようになった これなら毎 e グラム当たり π 円の商品も計算できるようになりました
これで値も見れちゃいます
これでやっと念願の比較ができました!商品 C が一番安いことがわかりました。
軽く結果ランキングをポール風にしてみた
ソースコードを Github にて公開しました
アプリ自体もホストしました
携帯のような細いスクリーンも対応した
沢山の微調整を経て大分綺麗になったのではないか
アイコンもデザインしました
草……ロゴ逆やん
このように一番高いやつと一番安いやつにアイコンをつけた……なんか結構 opinionated な感じ(お得なのが一番良くて、一番高いのはよくないみたいな)になってしまったけど、俗ではあるけど一消費者としてはやはり自然にそういう感じてしまうからな
index を min、max の計算の後知りたいから、こんなくどいアルゴリズムにしたけど、まあちゃんと動いてるし……
function getMinMax(items: Item[]) {
return items.reduce((acc: MinMax, ele: Item, ind: number) => {
const price = calculatePrice(ele.value, ele.amount, NaN)
if (isNaN(price)) {
return acc
}
if (price > acc.max.value) {
acc.max = {
index: ind,
value: price
}
}
if (price < acc.min.value) {
acc.min = {
index: ind,
value: price
}
}
return acc
}, {
min: {
index: -1,
value: Infinity
},
max: {
index: -1,
value: -Infinity
}
})
}
最大値と最小値を計算するアルゴリズムをもっとロバストにした
// 基本的に初期値が [] の default map
class PriceMap extends Map<number, number[]> {
get(k: number): number[] {
if (this.has(k)) {
return super.get(k)
} else {
const v = []
this.set(k, v)
return v
}
}
}
// 価格から index の 1-to-n 関係(全射)
function createPriceMap(prices: number[]): PriceMap {
return prices.reduce((map: PriceMap, price: number, index: number) => {
map.get(price).push(index)
return map
}, new PriceMap())
}
interface MinMax {
min?: {
value: number,
indices: number[],
},
max?: {
value: number,
indices: number[],
}
}
function createMinMax(priceMap: PriceMap): MinMax {
const sorted = [...priceMap.entries()].filter(([value,]) => !isNaN(value)).sort(([valA,], [valB,]) => {
return valA - valB
})
if (sorted.length <= 1) {
return {}
}
const [valueMin, indexMin] = sorted[0]
const [valueMax, indexMax] = sorted[sorted.length - 1]
return {
min: {
value: valueMin,
indices: indexMin,
},
max: {
value: valueMax,
indices: indexMax,
}
}
}
$: prices = items.map(({ value, amount }) => calculatePrice(value, amount))
$: priceMap = createPriceMap(prices)
$: minmax = createMinMax(priceMap)