Compare commits
No commits in common. "f3b1656f34d9a3416a2323e9457ca7991e4e4b98" and "eb20849bd85314bbb92154085bf803037fe6fa5d" have entirely different histories.
f3b1656f34
...
eb20849bd8
23
README.md
23
README.md
@ -15,24 +15,19 @@ following principles will guide its development.
|
|||||||
score keeping tool. Logical expansions, like synching a session between users / devices, will
|
score keeping tool. Logical expansions, like synching a session between users / devices, will
|
||||||
not be implemented, because they would be too complicated for the time I intend to spend on
|
not be implemented, because they would be too complicated for the time I intend to spend on
|
||||||
maintenance.
|
maintenance.
|
||||||
|
|
||||||
2. **Simple and stable dependencies:** I have learned in past projects that fast moving
|
2. **Simple and stable dependencies:** I have learned in past projects that fast moving
|
||||||
environments, like many modern JS frameworks, are very tedious to keep up with. Therefore all
|
environments, like many modern JS frameworks, are very tedious to keep up with. Therefore all
|
||||||
libraries must be stable and consistent. Also, I don't want to spend much time wrangling npm.
|
libraries must be stable and consistent. Also, I don't want to spend much time wrangling npm.
|
||||||
Therefore all dependencies must be vendorable as a couple of files.
|
Therefore all dependencies must be vendorable as a couple of files.
|
||||||
|
|
||||||
3. **Browser based development:** I don't want to spend a lot of time on build tools, transpilers,
|
3. **Browser based development:** I don't want to spend a lot of time on build tools, transpilers,
|
||||||
and similar things. All code has to be able to run in the browser in the form it is written. All
|
and similar things. All code has to be able to run in the browser in the form it is written. All
|
||||||
dev tools (like the testing framework) have to be able to run in the browser.
|
dev tools (like the testing framework) have to be able to run in the browser.
|
||||||
|
|
||||||
4. **Targetting Baseline:** The limited time for maintenance means I won't be able to do testing
|
4. **Targetting Baseline:** The limited time for maintenance means I won't be able to do testing
|
||||||
for all browser/version/os tripples. Instead, I'll target "baseline widely available" and rely
|
for all browser/version/os tripples. Instead, I'll target "baseline widely available" and rely
|
||||||
on it's correctness for portability. I'll also use features that are "baseline newly available",
|
on it's correctness for portability. I'll also use features that are "baseline newly available",
|
||||||
but only with feature checking, which I'll only do for them.
|
but only with feature checking, which I'll only do for them.
|
||||||
|
|
||||||
5. **Extensive tests:** I don't want to spend a lot of time on bug hunting, therefore everything
|
5. **Extensive tests:** I don't want to spend a lot of time on bug hunting, therefore everything
|
||||||
that can be tested automatically should be.
|
that can be tested automatically should be.
|
||||||
|
|
||||||
6. **Good documentation:** I'll most certainly forget how some things work at some point. Thus it
|
6. **Good documentation:** I'll most certainly forget how some things work at some point. Thus it
|
||||||
is paramount to keep a good documentation, so I won't have to read through everything again.
|
is paramount to keep a good documentation, so I won't have to read through everything again.
|
||||||
|
|
||||||
@ -43,21 +38,9 @@ have a cost. While I have deemed it to be worthwhile in this case, I consider it
|
|||||||
least document the disadvantages.
|
least document the disadvantages.
|
||||||
|
|
||||||
1. No access to a lot of JavaScripts modern ecosystem.
|
1. No access to a lot of JavaScripts modern ecosystem.
|
||||||
|
|
||||||
2. No access to compile time features such as actual typechecking.
|
2. No access to compile time features such as actual typechecking.
|
||||||
|
|
||||||
3. More network load that strictly necessary.
|
3. More network load that strictly necessary.
|
||||||
|
4. Less performance than what would be possible.
|
||||||
Build tools can provide minification, bundling and tree shaking. All of these are not available
|
|
||||||
to this project, but likely would decrease the total amount of data needed to be transfered.
|
|
||||||
However, likely it wouldn't actually be all that much, because it's a rather small application,
|
|
||||||
and it does its own caching with the service worker.
|
|
||||||
|
|
||||||
Also, most of the icons font could propably be cut away with some build tool. While I could do
|
|
||||||
that manually, it'd be too much hassle if I ever needed an additional icon.
|
|
||||||
|
|
||||||
4. Certain kinds of testing are impossible. For example, it's not really possible to test the
|
|
||||||
service worker from within the browser. Also, automated testing on pushes is not doable.
|
|
||||||
|
|
||||||
### Violations
|
### Violations
|
||||||
|
|
||||||
@ -67,11 +50,13 @@ following:
|
|||||||
1. The `jsconfig.json` file is a build tool configuration file. It shouldn't be needed, as the
|
1. The `jsconfig.json` file is a build tool configuration file. It shouldn't be needed, as the
|
||||||
project doesn't use any build tools. However, it allows the LSP to be more usefull, thus
|
project doesn't use any build tools. However, it allows the LSP to be more usefull, thus
|
||||||
justifying its existence.
|
justifying its existence.
|
||||||
|
|
||||||
2. Nested CSS. It is so much more managable than repeating the same selectors over and over. Keep
|
2. Nested CSS. It is so much more managable than repeating the same selectors over and over. Keep
|
||||||
in mind that the principles are to make the maintenence of this side project viable for me in
|
in mind that the principles are to make the maintenence of this side project viable for me in
|
||||||
the long term. In ~4 months from this writing (2026-03-04) they become baseline widely available
|
the long term. In ~4 months from this writing (2026-03-04) they become baseline widely available
|
||||||
and I would want to rewrite all the styles then. I deem this to be a worthwhile trade-off.
|
and I would want to rewrite all the styles then. I deem this to be a worthwhile trade-off.
|
||||||
|
3. The `:has()` CSS pseudo-class. While it's not as useful, it becomes baseline widely available at
|
||||||
|
the same time as nested CSS. Might as well use it then, as a non-supporting browser can't be
|
||||||
|
used either way.
|
||||||
|
|
||||||
Structure
|
Structure
|
||||||
---------
|
---------
|
||||||
|
|||||||
20
index.html
20
index.html
@ -5,18 +5,9 @@
|
|||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<title>Watterblock</title>
|
<title>Watterblock</title>
|
||||||
|
|
||||||
<link rel="stylesheet" href="/vendored/normalize-8.0.1.css">
|
<link rel="stylesheet" href="/vendored/normalize-8.0.1.css">
|
||||||
<link rel="stylesheet" href="/style.css">
|
<link rel="stylesheet" href="/style.css">
|
||||||
<link rel="stylesheet" href="/vendored/material-icons.css" />
|
<link rel="stylesheet" href="/vendored/material-icons.css" />
|
||||||
<noscript>
|
|
||||||
<style>
|
|
||||||
._yesscript {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</noscript>
|
|
||||||
|
|
||||||
<script type="module">
|
<script type="module">
|
||||||
// initialize DB early
|
// initialize DB early
|
||||||
import WbDb from "/data/db.js";
|
import WbDb from "/data/db.js";
|
||||||
@ -24,22 +15,15 @@
|
|||||||
</script>
|
</script>
|
||||||
<script src="/vendored/mithril-2.3.8.js" defer></script>
|
<script src="/vendored/mithril-2.3.8.js" defer></script>
|
||||||
<script src="/index.js" type="module"></script>
|
<script src="/index.js" type="module"></script>
|
||||||
|
|
||||||
<meta name="application-name" content="Watterblock">
|
|
||||||
<meta name="author" content="Adrian Wannenmacher">
|
|
||||||
<meta name="description" lang="de-AT"
|
|
||||||
content="Einfach zu verwendender Watterblock, der die Daten lokal im Browser speichert.">
|
|
||||||
<meta name="keywords" content="Watten,Block,Spiel,Mitschrift">
|
|
||||||
<meta name="theme-color" content="lch(86 84 71)" media="(prefers-color-scheme: dark)">
|
|
||||||
<meta name="theme-color" content="lch(20 87 292)" media="(prefers-color-scheme: light)">
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="wb-layout">
|
<body class="wb-layout">
|
||||||
<div class="wb-splash _yesscript">
|
<div class="wb-splash" id="initial" style="display: none;">
|
||||||
<div class="spinner"></div>
|
<div class="spinner"></div>
|
||||||
<h1>Watterblock</h1>
|
<h1>Watterblock</h1>
|
||||||
<p>I lad grad…</p>
|
<p>I lad grad…</p>
|
||||||
</div>
|
</div>
|
||||||
|
<script>document.getElementById("initial").removeAttribute("style")</script>
|
||||||
|
|
||||||
<noscript class="wb-splash">
|
<noscript class="wb-splash">
|
||||||
<h1>Watterblock</h1>
|
<h1>Watterblock</h1>
|
||||||
|
|||||||
@ -59,7 +59,7 @@ export default class Game extends EventTarget {
|
|||||||
super();
|
super();
|
||||||
if (value === undefined || value instanceof GameRules) {
|
if (value === undefined || value instanceof GameRules) {
|
||||||
if (value instanceof GameRules)
|
if (value instanceof GameRules)
|
||||||
this.#rules = new GameRules(value);
|
this.#rules = value;
|
||||||
|
|
||||||
this.#currentRound = new Round(
|
this.#currentRound = new Round(
|
||||||
this.#rules.raisingLimit(0), this.#rules.raisingLimit(0));
|
this.#rules.raisingLimit(0), this.#rules.raisingLimit(0));
|
||||||
|
|||||||
@ -53,18 +53,6 @@ export default function() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
QUnit.test("rules stay static after construction", function(assert) {
|
|
||||||
let rules = new GameRules();
|
|
||||||
rules.goal = 15;
|
|
||||||
|
|
||||||
let game = new Game(rules);
|
|
||||||
assert.strictEqual(game.rules.goal, 15, "correct goal");
|
|
||||||
|
|
||||||
rules.goal = 17;
|
|
||||||
assert.strictEqual(game.rules.goal, 15, "games rules didn't change");
|
|
||||||
assert.notStrictEqual(game.rules.goal, rules.goal, "goals are different");
|
|
||||||
});
|
|
||||||
|
|
||||||
QUnit.test("single round played", function(assert) {
|
QUnit.test("single round played", function(assert) {
|
||||||
let game = new Game();
|
let game = new Game();
|
||||||
game.currentRound.winner = Team.We;
|
game.currentRound.winner = Team.We;
|
||||||
|
|||||||
@ -130,7 +130,7 @@ export default class Session extends EventTarget {
|
|||||||
/** Add another round if there is no current one. */
|
/** Add another round if there is no current one. */
|
||||||
anotherGame() {
|
anotherGame() {
|
||||||
if (this.#currentGame === null) {
|
if (this.#currentGame === null) {
|
||||||
this.#currentGame = new Game(this.#rules);
|
this.#currentGame = new Game(new GameRules(this.#rules));
|
||||||
this.#currentGame.addEventListener(
|
this.#currentGame.addEventListener(
|
||||||
Game.EVENT_CHANGE, this.#boundHandleGameChange);
|
Game.EVENT_CHANGE, this.#boundHandleGameChange);
|
||||||
this.#changed();
|
this.#changed();
|
||||||
|
|||||||
@ -60,6 +60,17 @@ export default function() {
|
|||||||
assert.notStrictEqual(session.currentGame, null, "game in progress");
|
assert.notStrictEqual(session.currentGame, null, "game in progress");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
QUnit.test("session rule change doesn't affect games", function(assert) {
|
||||||
|
let session = new Session();
|
||||||
|
session.anotherGame();
|
||||||
|
session.rules.goal = 7;
|
||||||
|
assert.notStrictEqual(
|
||||||
|
session.currentGame.rules.goal,
|
||||||
|
session.rules.goal,
|
||||||
|
"game rules have been copied",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
QUnit.test("single game finished", function(assert) {
|
QUnit.test("single game finished", function(assert) {
|
||||||
let session = new Session();
|
let session = new Session();
|
||||||
session.anotherGame();
|
session.anotherGame();
|
||||||
|
|||||||
14
style.css
14
style.css
@ -30,7 +30,6 @@ html {
|
|||||||
/* regular main colors */
|
/* regular main colors */
|
||||||
--color-regular-text: lch(100 0 0);
|
--color-regular-text: lch(100 0 0);
|
||||||
--color-regular-background: lch(10 0 0);
|
--color-regular-background: lch(10 0 0);
|
||||||
/* also in index.html as meta theme-color, update there too */
|
|
||||||
--color-regular-accent: lch(86 84 71);
|
--color-regular-accent: lch(86 84 71);
|
||||||
|
|
||||||
/* regular derived colors */
|
/* regular derived colors */
|
||||||
@ -60,30 +59,29 @@ html {
|
|||||||
/* regular main colors */
|
/* regular main colors */
|
||||||
--color-regular-text: lch(0 0 0);
|
--color-regular-text: lch(0 0 0);
|
||||||
--color-regular-background: lch(100 0 0);
|
--color-regular-background: lch(100 0 0);
|
||||||
/* also in index.html as meta theme-color, update there too */
|
--color-regular-accent: lch(14 77 304);
|
||||||
--color-regular-accent: lch(30 87 292);
|
|
||||||
|
|
||||||
/* regular derived colors */
|
/* regular derived colors */
|
||||||
--color-regular-disabled-text: lch(25 0 0);
|
--color-regular-disabled-text: lch(25 0 0);
|
||||||
--color-regular-disabled-background: lch(75 0 0);
|
--color-regular-disabled-background: lch(75 0 0);
|
||||||
--color-regular-disabled-accent: lch(45 87 292);
|
--color-regular-disabled-accent: lch(30 77 304);
|
||||||
--color-regular-focus-text: lch(10 0 0);
|
--color-regular-focus-text: lch(10 0 0);
|
||||||
--color-regular-focus-background: lch(90 0 0);
|
--color-regular-focus-background: lch(90 0 0);
|
||||||
--color-regular-focus-accent: lch(35 87 292);
|
--color-regular-focus-accent: lch(20 77 304);
|
||||||
--color-regular-field: lch(95 0 0);
|
--color-regular-field: lch(95 0 0);
|
||||||
|
|
||||||
/* alternate main colors */
|
/* alternate main colors */
|
||||||
--color-alternate-text: lch(0 0 0);
|
--color-alternate-text: lch(0 0 0);
|
||||||
--color-alternate-background: lch(90 0 0);
|
--color-alternate-background: lch(90 0 0);
|
||||||
--color-alternate-accent: lch(20 87 292);
|
--color-alternate-accent: lch(14 77 304);
|
||||||
|
|
||||||
/* alternate derived colors */
|
/* alternate derived colors */
|
||||||
--color-alternate-disabled-text: lch(25 0 0);
|
--color-alternate-disabled-text: lch(25 0 0);
|
||||||
--color-alternate-disabled-background: lch(65 0 0);
|
--color-alternate-disabled-background: lch(65 0 0);
|
||||||
--color-alternate-disabled-accent: lch(35 87 292);
|
--color-alternate-disabled-accent: lch(30 77 304);
|
||||||
--color-alternate-focus-text: lch(10 0 0);
|
--color-alternate-focus-text: lch(10 0 0);
|
||||||
--color-alternate-focus-background: lch(80 0 0);
|
--color-alternate-focus-background: lch(80 0 0);
|
||||||
--color-alternate-focus-accent: lch(25 87 292);
|
--color-alternate-focus-accent: lch(20 77 304);
|
||||||
--color-alternate-field: lch(95 0 0);
|
--color-alternate-field: lch(95 0 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -27,10 +27,7 @@ export default class SessionView {
|
|||||||
]),
|
]),
|
||||||
|
|
||||||
this.#headOpen
|
this.#headOpen
|
||||||
? m("._alternate._apply.wb-box", m(SessionHead, {
|
? m("._alternate._apply.wb-box", m(SessionHead, { model }))
|
||||||
model,
|
|
||||||
noteNextGame: true,
|
|
||||||
}))
|
|
||||||
: null,
|
: null,
|
||||||
|
|
||||||
m("section.spacer", [
|
m("section.spacer", [
|
||||||
|
|||||||
@ -4,24 +4,10 @@ import { RaisingRule } from "/models/game_rules.js";
|
|||||||
import Session from "/models/session.js";
|
import Session from "/models/session.js";
|
||||||
|
|
||||||
export default class SessionHead {
|
export default class SessionHead {
|
||||||
/** The attributes a `SessionHead` component can handle.
|
/** @param {{ attrs: { model: Session } }} param The session model to use. */
|
||||||
*
|
view({ attrs: { model } }) {
|
||||||
* @typedef {Object} SessionHeadAttrs
|
|
||||||
* @property {Session} model The session model to use.
|
|
||||||
* @property {boolean} noteNextGame
|
|
||||||
* If set, show a message that rules only come into effect for the next game.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** @param {{ attrs: SessionHeadAttrs }} param Parameters for the component */
|
|
||||||
view({ attrs: { model, noteNextGame } }) {
|
|
||||||
return m("section", [
|
return m("section", [
|
||||||
m("h3._positioned", "Satzeinstellungen"),
|
m("h3._positioned", "Satzeinstellungen"),
|
||||||
noteNextGame
|
|
||||||
? m("p",
|
|
||||||
"Obacht, wennst di Regln ändast, geltn di neien erst fürs naxte ",
|
|
||||||
"Spiel."
|
|
||||||
)
|
|
||||||
: null,
|
|
||||||
m("section", [
|
m("section", [
|
||||||
m("h4", "Teamnamen"),
|
m("h4", "Teamnamen"),
|
||||||
m("label.wb-field", [
|
m("label.wb-field", [
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user