/* Hurry Curry! - a game about cooking Copyright (C) 2025 Hurry Curry! Contributors This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, version 3 of the License only. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ import { message_str } from "./locale.ts"; import { float, int, Message, PacketC, PlayerID, VoteSubject } from "./protocol.ts"; import { System } from "./system.ts"; import { lerp_exp } from "./util.ts"; interface ActiveVote { total: int, agree: int, reject: int, initiated_by: PlayerID, subject: VoteSubject, message: Message, initial_timeout: float, timeout: float, anim_box: float, anim_cast: float, done: boolean } export class SVote extends System { active?: ActiveVote override tick(dt: number) { if (!this.active) return const a = this.active a.anim_cast *= Math.exp(-dt * 5); a.anim_box = lerp_exp(a.anim_box, a.done ? 1.1 : 0, dt * 5) a.timeout -= dt a.timeout = Math.max(a.timeout, 0) if (a.anim_box > 1) delete this.active } override draw(ctx: CanvasRenderingContext2D) { if (!this.active) return const a = this.active const w = 300 const h = 200 const p = 20 ctx.save() ctx.translate(-w * a.anim_box, 0) ctx.translate(p, p) let r = 1, g = 1, b = 1 if (a.anim_cast > 0) { r -= a.anim_cast; b -= a.anim_cast } if (a.anim_cast < 0) { g += a.anim_cast; b += a.anim_cast } ctx.fillStyle = `rgba(${r * 255}, ${g * 255}, ${b * 255}, 0.67)` ctx.fillRect(0, 0, 300, 200) ctx.font = "20px sans-serif" ctx.fillStyle = "black" ctx.fillText(message_str(a.message), p, p + 20, w - p * 2) ctx.fillStyle = "#0008" ctx.fillRect(0, 0, (1 - a.timeout / a.initial_timeout) * w, 10) const bar_height = 50 ctx.translate(p, h - bar_height - p) ctx.scale(w - p * 2, bar_height) ctx.fillStyle = "#0008" ctx.fillRect(0, 0, 1, 1) ctx.fillRect(0.49, 0, 0.02, 1) ctx.fillStyle = "#51ff00" ctx.fillRect(0, 0, a.agree / a.total, 1) ctx.fillStyle = "#ff0000" ctx.fillRect(1 - (a.reject / a.total), 0, (a.reject / a.total), 1) ctx.restore() } override packet(p: PacketC): void { if (p.type == "vote_started") { this.active = { agree: 0, reject: 0, total: 0, initiated_by: p.initiated_by, message: p.message, subject: p.subject, anim_box: 1, anim_cast: 0, done: false, initial_timeout: p.timeout, timeout: p.timeout } } else if (p.type == "vote_ended" && this.active) { this.active.done = true } else if (p.type == "vote_updated" && this.active) { const a = this.active; if (p.agree > a.agree) a.anim_cast += 1 if (p.reject > a.reject) a.anim_cast -= 1 a.agree = p.agree a.reject = p.reject a.total = p.total } } }