soja-cli 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +18 -0
- package/README.md +117 -0
- package/dist/application/chat.js +1 -0
- package/dist/application/filters.js +27 -0
- package/dist/application/import.js +1 -0
- package/dist/application/ports.js +1 -0
- package/dist/application/repository-root.js +18 -0
- package/dist/application/services/backup-service.js +93 -0
- package/dist/application/services/folder-service.js +116 -0
- package/dist/application/services/git-workflow-service.js +593 -0
- package/dist/application/services/index.js +24 -0
- package/dist/application/services/project-service.js +129 -0
- package/dist/application/services/session-service.js +52 -0
- package/dist/application/services/task-service.js +350 -0
- package/dist/application/services/update-service.js +60 -0
- package/dist/application/services/workspace-service.js +81 -0
- package/dist/application/timeline.js +83 -0
- package/dist/application/types.js +1 -0
- package/dist/application/validation.js +30 -0
- package/dist/bootstrap.js +91 -0
- package/dist/cli/commands/access.js +60 -0
- package/dist/cli/commands/account.js +203 -0
- package/dist/cli/commands/args.js +27 -0
- package/dist/cli/commands/backup.js +70 -0
- package/dist/cli/commands/chat.js +133 -0
- package/dist/cli/commands/dev.js +59 -0
- package/dist/cli/commands/folders.js +59 -0
- package/dist/cli/commands/git-ops.js +200 -0
- package/dist/cli/commands/import.js +48 -0
- package/dist/cli/commands/info.js +82 -0
- package/dist/cli/commands/project.js +108 -0
- package/dist/cli/commands/start.js +34 -0
- package/dist/cli/commands/sync.js +43 -0
- package/dist/cli/commands/task.js +309 -0
- package/dist/cli/commands/tui.js +43 -0
- package/dist/cli/commands/update.js +20 -0
- package/dist/cli/commands/workspace.js +55 -0
- package/dist/cli/index.js +103 -0
- package/dist/cli/output.js +56 -0
- package/dist/cli/prompt.js +28 -0
- package/dist/cli/runtime.js +43 -0
- package/dist/config/config.js +103 -0
- package/dist/config/credentials.js +68 -0
- package/dist/config/paths.js +18 -0
- package/dist/config/server.js +21 -0
- package/dist/config/version.js +7 -0
- package/dist/data/local/activity.js +33 -0
- package/dist/data/local/clock.js +1 -0
- package/dist/data/local/comments.js +27 -0
- package/dist/data/local/index.js +48 -0
- package/dist/data/local/projects.js +53 -0
- package/dist/data/local/tasks.js +104 -0
- package/dist/data/local/users.js +38 -0
- package/dist/data/local/workspaces.js +55 -0
- package/dist/data/remote/api-client.js +103 -0
- package/dist/data/remote/live.js +93 -0
- package/dist/data/repositories.js +1 -0
- package/dist/data/sync/chat.js +242 -0
- package/dist/data/sync/engine.js +459 -0
- package/dist/data/sync/importer.js +156 -0
- package/dist/data/sync/index.js +109 -0
- package/dist/data/sync/services.js +263 -0
- package/dist/data/sync/store.js +200 -0
- package/dist/database/client.js +76 -0
- package/dist/database/migrate.js +27 -0
- package/dist/database/migrations/0000_init.sql +100 -0
- package/dist/database/migrations/0001_git-operations.sql +19 -0
- package/dist/database/migrations/0002_merge-detection.sql +19 -0
- package/dist/database/migrations/0003_sync-replica.sql +40 -0
- package/dist/database/migrations/0004_chat-replica.sql +52 -0
- package/dist/database/migrations/0005_pr-events.sql +18 -0
- package/dist/database/migrations/0006_archive.sql +20 -0
- package/dist/database/migrations/meta/0000_snapshot.json +710 -0
- package/dist/database/migrations/meta/0001_snapshot.json +717 -0
- package/dist/database/migrations/meta/0002_snapshot.json +724 -0
- package/dist/database/migrations/meta/0003_snapshot.json +972 -0
- package/dist/database/migrations/meta/0004_snapshot.json +1168 -0
- package/dist/database/migrations/meta/0005_snapshot.json +1168 -0
- package/dist/database/migrations/meta/0006_snapshot.json +1183 -0
- package/dist/database/migrations/meta/_journal.json +55 -0
- package/dist/database/schema.js +170 -0
- package/dist/dev/seed.js +84 -0
- package/dist/domain/activity.js +22 -0
- package/dist/domain/chat.js +21 -0
- package/dist/domain/entities.js +1 -0
- package/dist/domain/errors.js +23 -0
- package/dist/domain/naming.js +33 -0
- package/dist/domain/task.js +140 -0
- package/dist/domain/workflow.js +23 -0
- package/dist/git/cli-git.js +363 -0
- package/dist/git/console.js +37 -0
- package/dist/git/diagnose.js +145 -0
- package/dist/git/merge-evidence.js +23 -0
- package/dist/git/releases.js +95 -0
- package/dist/git/types.js +16 -0
- package/dist/ui/App.js +71 -0
- package/dist/ui/Shell.js +211 -0
- package/dist/ui/app-state.js +213 -0
- package/dist/ui/branding/CompactLogo.js +8 -0
- package/dist/ui/branding/Logo.js +22 -0
- package/dist/ui/branding/Splash.js +21 -0
- package/dist/ui/branding/brand.js +23 -0
- package/dist/ui/chrome/Sidebar.js +50 -0
- package/dist/ui/chrome/StatusBar.js +26 -0
- package/dist/ui/chrome/Toast.js +11 -0
- package/dist/ui/chrome/TopBar.js +10 -0
- package/dist/ui/chrome/context.js +33 -0
- package/dist/ui/components/ConsoleLines.js +16 -0
- package/dist/ui/components/EmptyState.js +8 -0
- package/dist/ui/components/Labels.js +25 -0
- package/dist/ui/components/PullRequestLabel.js +27 -0
- package/dist/ui/components/TaskTable.js +41 -0
- package/dist/ui/components/TextField.js +11 -0
- package/dist/ui/components/TextInput.js +29 -0
- package/dist/ui/components/task-columns.js +27 -0
- package/dist/ui/copy.js +23 -0
- package/dist/ui/hooks/use-commands.js +58 -0
- package/dist/ui/hooks/use-flows.js +254 -0
- package/dist/ui/hooks/use-layout.js +36 -0
- package/dist/ui/hooks/use-list.js +28 -0
- package/dist/ui/hooks/use-measure.js +22 -0
- package/dist/ui/hooks/use-query.js +29 -0
- package/dist/ui/hooks/use-task-actions.js +450 -0
- package/dist/ui/hooks/use-terminal-size.js +19 -0
- package/dist/ui/input/KeyProvider.js +101 -0
- package/dist/ui/input/dispatcher.js +26 -0
- package/dist/ui/input/list-navigation.js +38 -0
- package/dist/ui/input/mouse.js +78 -0
- package/dist/ui/input/text-editing.js +62 -0
- package/dist/ui/kit/Badge.js +8 -0
- package/dist/ui/kit/Button.js +13 -0
- package/dist/ui/kit/Clickable.js +14 -0
- package/dist/ui/kit/Gauge.js +9 -0
- package/dist/ui/kit/Keycap.js +7 -0
- package/dist/ui/kit/Panel.js +30 -0
- package/dist/ui/kit/ScrollBar.js +14 -0
- package/dist/ui/kit/Spinner.js +9 -0
- package/dist/ui/kit/Tabs.js +12 -0
- package/dist/ui/mascot/AgentScene.js +30 -0
- package/dist/ui/mascot/Mascot.js +26 -0
- package/dist/ui/mascot/ansi.js +25 -0
- package/dist/ui/mascot/engine.js +146 -0
- package/dist/ui/mascot/index.js +6 -0
- package/dist/ui/mascot/palette.js +18 -0
- package/dist/ui/mascot/scenes/bugHunt.js +115 -0
- package/dist/ui/mascot/scenes/celebrate.js +76 -0
- package/dist/ui/mascot/scenes/cleaning.js +156 -0
- package/dist/ui/mascot/scenes/clockIn.js +105 -0
- package/dist/ui/mascot/scenes/deadline.js +125 -0
- package/dist/ui/mascot/scenes/empty.js +149 -0
- package/dist/ui/mascot/scenes/fire.js +138 -0
- package/dist/ui/mascot/scenes/index.js +25 -0
- package/dist/ui/mascot/scenes/planning.js +73 -0
- package/dist/ui/mascot/scenes/resting.js +90 -0
- package/dist/ui/mascot/scenes/syncing.js +116 -0
- package/dist/ui/mascot/scenes/working.js +193 -0
- package/dist/ui/mascot/selection.js +32 -0
- package/dist/ui/mascot/states.js +25 -0
- package/dist/ui/navigation/routes.js +17 -0
- package/dist/ui/overlays/CommitOverlay.js +93 -0
- package/dist/ui/overlays/ConfirmOverlay.js +42 -0
- package/dist/ui/overlays/GitLogOverlay.js +22 -0
- package/dist/ui/overlays/GitRunOverlay.js +94 -0
- package/dist/ui/overlays/NewTaskOverlay.js +117 -0
- package/dist/ui/overlays/OverlayFrame.js +35 -0
- package/dist/ui/overlays/PickerOverlay.js +72 -0
- package/dist/ui/overlays/PromptOverlay.js +51 -0
- package/dist/ui/overlays/SearchOverlay.js +49 -0
- package/dist/ui/overlays/options.js +29 -0
- package/dist/ui/overlays/types.js +1 -0
- package/dist/ui/screens/AccessScreen.js +91 -0
- package/dist/ui/screens/ChatScreen.js +450 -0
- package/dist/ui/screens/HelpScreen.js +99 -0
- package/dist/ui/screens/ProjectsScreen.js +66 -0
- package/dist/ui/screens/ScreenFrame.js +14 -0
- package/dist/ui/screens/SetupScreen.js +79 -0
- package/dist/ui/screens/TaskListScreen.js +152 -0
- package/dist/ui/screens/TaskScreen.js +193 -0
- package/dist/ui/screens/WelcomeScreen.js +254 -0
- package/dist/ui/screens/WorkspacesScreen.js +64 -0
- package/dist/ui/theme/detect.js +59 -0
- package/dist/ui/theme/theme.js +135 -0
- package/dist/utils/editor.js +37 -0
- package/dist/utils/errors.js +23 -0
- package/dist/utils/text.js +60 -0
- package/dist/utils/time.js +25 -0
- package/docs/NPM_PUBLISH.md +35 -0
- package/docs/PRIVACY.md +38 -0
- package/package.json +74 -0
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { blink, drawGround, mirror, rng, soilLine, withFace } from '../engine.js';
|
|
2
|
+
const W = 78;
|
|
3
|
+
const H = 13;
|
|
4
|
+
const G = 11;
|
|
5
|
+
const RUN_A = [' .-. ', '(o.o)=', '( ) ', " / \\ "];
|
|
6
|
+
const RUN_B = [' .-. ', '(o.o)=', '( ) ', " |\\ "];
|
|
7
|
+
const TYPE_A = [' .-. ', '(o.o) ', '( )/'];
|
|
8
|
+
const TYPE_B = [' .-. ', '(o.o) ', '( )\\'];
|
|
9
|
+
export const deadline = {
|
|
10
|
+
id: 'deadline',
|
|
11
|
+
title: 'Contra reloj',
|
|
12
|
+
useFor: 'Tareas vencidas o por vencer',
|
|
13
|
+
width: W,
|
|
14
|
+
height: H,
|
|
15
|
+
create(seed = 10) {
|
|
16
|
+
const r = rng(seed);
|
|
17
|
+
const soil = [soilLine(W, r)];
|
|
18
|
+
const runners = [
|
|
19
|
+
{ x: 24, v: 0.9, n: 1 },
|
|
20
|
+
{ x: 50, v: -1.1, n: 2 },
|
|
21
|
+
{ x: 66, v: -0.8, n: 3 },
|
|
22
|
+
];
|
|
23
|
+
let t = 0;
|
|
24
|
+
let secs = 59;
|
|
25
|
+
let delivered = 0;
|
|
26
|
+
let doneT = 0;
|
|
27
|
+
let papers = [];
|
|
28
|
+
let sweat = [];
|
|
29
|
+
let taps = 0;
|
|
30
|
+
return {
|
|
31
|
+
step() {
|
|
32
|
+
t++;
|
|
33
|
+
if (doneT) {
|
|
34
|
+
doneT--;
|
|
35
|
+
if (!doneT)
|
|
36
|
+
secs = 59;
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
if (t % 5 === 0)
|
|
40
|
+
secs--;
|
|
41
|
+
if (secs <= 0) {
|
|
42
|
+
secs = 0;
|
|
43
|
+
doneT = 30;
|
|
44
|
+
delivered++;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
const speedUp = !doneT && secs < 15 ? 1.4 : 1;
|
|
48
|
+
for (const a of runners) {
|
|
49
|
+
if (doneT)
|
|
50
|
+
continue;
|
|
51
|
+
a.x += a.v * speedUp;
|
|
52
|
+
if (a.x < 22 || a.x > W - 7) {
|
|
53
|
+
a.v = -a.v;
|
|
54
|
+
a.x = Math.max(22, Math.min(W - 7, a.x));
|
|
55
|
+
if (r() < 0.6)
|
|
56
|
+
papers.push({ x: a.x + 3, y: G - 3, vx: (r() - 0.5) * 1.2, vy: -0.6, ch: '▭', tone: 'paper' });
|
|
57
|
+
}
|
|
58
|
+
if (t % 6 === a.n)
|
|
59
|
+
sweat.push({ x: a.x + (a.v > 0 ? 0 : 5), y: G - 4, vx: -Math.sign(a.v) * 0.4, vy: -0.3, ch: "'", tone: 'water' });
|
|
60
|
+
}
|
|
61
|
+
if (!doneT)
|
|
62
|
+
taps++;
|
|
63
|
+
for (const p of papers) {
|
|
64
|
+
p.x += p.vx;
|
|
65
|
+
p.y += p.vy;
|
|
66
|
+
p.vy += 0.06;
|
|
67
|
+
p.vx *= 0.97;
|
|
68
|
+
}
|
|
69
|
+
papers = papers.filter((p) => p.y < G);
|
|
70
|
+
for (const s of sweat) {
|
|
71
|
+
s.x += s.vx;
|
|
72
|
+
s.y += s.vy;
|
|
73
|
+
s.vy += 0.1;
|
|
74
|
+
}
|
|
75
|
+
sweat = sweat.filter((s) => s.y < G);
|
|
76
|
+
},
|
|
77
|
+
draw(c) {
|
|
78
|
+
drawGround(c, G, soil);
|
|
79
|
+
const urgent = !doneT && secs < 15;
|
|
80
|
+
const clockTone = doneT ? 'good' : urgent && t % 6 < 3 ? 'bad' : 'text';
|
|
81
|
+
c.put(29, 0, ' .--------------. ', 'rock');
|
|
82
|
+
c.put(29, 1, ' | | ', 'rock');
|
|
83
|
+
c.put(29, 2, " '--------------' ", 'rock');
|
|
84
|
+
c.put(doneT ? 33 : 34, 1, doneT ? 'entregado!' : `23:59:${String(secs).padStart(2, '0')}`, clockTone);
|
|
85
|
+
if (urgent) {
|
|
86
|
+
c.put(26, 1, '!!', 'bad');
|
|
87
|
+
c.put(49, 1, '!!', 'bad');
|
|
88
|
+
}
|
|
89
|
+
c.put(1, G - 3, '▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄', 'wood');
|
|
90
|
+
c.put(2, G - 2, '||', 'wood');
|
|
91
|
+
c.put(2, G - 1, '||', 'wood');
|
|
92
|
+
c.put(13, G - 2, '||', 'wood');
|
|
93
|
+
c.put(13, G - 1, '||', 'wood');
|
|
94
|
+
c.put(9, G - 6, '.----.', 'rock');
|
|
95
|
+
c.put(9, G - 5, '|' + (doneT ? ' ok ' : '#'.repeat(Math.floor(t / 2) % 5).padEnd(4, '_')) + '|', doneT ? 'good' : 'accent');
|
|
96
|
+
c.put(9, G - 4, "'----'", 'rock');
|
|
97
|
+
c.put(9, G - 5, '|', 'rock');
|
|
98
|
+
c.put(14, G - 5, '|', 'rock');
|
|
99
|
+
c.sprite(3, G - 6, withFace(taps % 2 ? TYPE_A : TYPE_B, doneT ? '^.^' : urgent ? '>.<' : 'O.O'), 'agent');
|
|
100
|
+
if (!doneT && t % 4 < 2)
|
|
101
|
+
c.put(7, G - 7, 'tap', 'cloud');
|
|
102
|
+
c.put(16, G - 4, '▭▭', 'paper');
|
|
103
|
+
c.put(16, G - 5, '▭', 'paper');
|
|
104
|
+
runners.forEach((a, i) => {
|
|
105
|
+
const face = doneT ? '^.^' : urgent ? '>.<' : blink(t, i, 'O.O');
|
|
106
|
+
let sp = doneT ? [' .-. ', '(o.o)', '( )', " ' ' "] : Math.floor(t / 2) % 2 ? RUN_A : RUN_B;
|
|
107
|
+
if (a.v < 0 && !doneT)
|
|
108
|
+
sp = mirror(sp);
|
|
109
|
+
c.sprite(a.x, G - 4, withFace(sp, face), 'agent');
|
|
110
|
+
if (!doneT)
|
|
111
|
+
c.put(a.v > 0 ? a.x + 6 : a.x - 1, G - 3, '▭', 'paper');
|
|
112
|
+
});
|
|
113
|
+
if (doneT && t % 8 < 5)
|
|
114
|
+
c.put(40, G - 6, '(lo logramos!)', 'good');
|
|
115
|
+
for (const p of papers)
|
|
116
|
+
c.put(p.x, p.y, p.ch, p.tone);
|
|
117
|
+
for (const s of sweat)
|
|
118
|
+
c.put(s.x, s.y, s.ch, s.tone);
|
|
119
|
+
},
|
|
120
|
+
status() {
|
|
121
|
+
return doneT ? `entregado a tiempo · ${delivered} entregas` : `vence en ${secs}s · ${delivered} entregas`;
|
|
122
|
+
},
|
|
123
|
+
};
|
|
124
|
+
},
|
|
125
|
+
};
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
/* eslint-disable prefer-const -- the bird list is mutated in place by the scene engine. */
|
|
2
|
+
import { blink, drawCloud, rng, soilLine, withFace } from '../engine.js';
|
|
3
|
+
const W = 78;
|
|
4
|
+
const H = 12;
|
|
5
|
+
const WATER_Y = 8;
|
|
6
|
+
const SHORE = 30;
|
|
7
|
+
const DOCK_L = 28;
|
|
8
|
+
const DOCK_R = 50;
|
|
9
|
+
const FISHER_X = 43;
|
|
10
|
+
const TREE = [' .--. ', ' ( ) ', '( ~ )', " '-..-' "];
|
|
11
|
+
const SIT_ROD = [' .-. ', '(o.o)/', '(___) '];
|
|
12
|
+
const SIT_PULL = [' .-. |', '(o.o)|', '(___) '];
|
|
13
|
+
export const empty = {
|
|
14
|
+
id: 'empty',
|
|
15
|
+
title: 'Pescando',
|
|
16
|
+
useFor: 'Lista vacía / sin tareas pendientes',
|
|
17
|
+
width: W,
|
|
18
|
+
height: H,
|
|
19
|
+
create(seed = 9) {
|
|
20
|
+
const r = rng(seed);
|
|
21
|
+
const soil = [soilLine(SHORE, r), soilLine(SHORE, r), soilLine(SHORE, r)];
|
|
22
|
+
let t = 0;
|
|
23
|
+
let fish = 0;
|
|
24
|
+
let boots = 0;
|
|
25
|
+
let phase = 'wait';
|
|
26
|
+
let k = 0;
|
|
27
|
+
let waitFor = 50;
|
|
28
|
+
let catchKind = 'fish';
|
|
29
|
+
let flying = null;
|
|
30
|
+
let happy = 0;
|
|
31
|
+
let zs = [];
|
|
32
|
+
let weed = -10;
|
|
33
|
+
let birds = [{ x: 70, y: 1 }];
|
|
34
|
+
return {
|
|
35
|
+
step() {
|
|
36
|
+
t++;
|
|
37
|
+
k++;
|
|
38
|
+
if (phase === 'wait' && k > waitFor) {
|
|
39
|
+
phase = 'bite';
|
|
40
|
+
k = 0;
|
|
41
|
+
}
|
|
42
|
+
else if (phase === 'bite' && k > 10) {
|
|
43
|
+
phase = 'pull';
|
|
44
|
+
k = 0;
|
|
45
|
+
catchKind = r() < 0.7 ? 'fish' : 'boot';
|
|
46
|
+
flying = { x: FISHER_X + 9, y: WATER_Y, vx: -0.9, vy: -0.9, ch: catchKind === 'fish' ? '><>' : '_|', tone: catchKind === 'fish' ? 'water' : 'wood' };
|
|
47
|
+
}
|
|
48
|
+
else if (phase === 'pull' && k > 14) {
|
|
49
|
+
phase = 'wait';
|
|
50
|
+
k = 0;
|
|
51
|
+
waitFor = 40 + Math.floor(r() * 50);
|
|
52
|
+
if (catchKind === 'fish')
|
|
53
|
+
fish++;
|
|
54
|
+
else
|
|
55
|
+
boots++;
|
|
56
|
+
happy = 16;
|
|
57
|
+
flying = null;
|
|
58
|
+
}
|
|
59
|
+
if (flying) {
|
|
60
|
+
flying.x += flying.vx;
|
|
61
|
+
flying.y += flying.vy;
|
|
62
|
+
flying.vy += 0.14;
|
|
63
|
+
if (flying.y > WATER_Y - 2)
|
|
64
|
+
flying.y = WATER_Y - 2;
|
|
65
|
+
}
|
|
66
|
+
if (happy)
|
|
67
|
+
happy--;
|
|
68
|
+
if (t % 16 === 0)
|
|
69
|
+
zs.push({ x: 8, y: WATER_Y - 3, l: 0 });
|
|
70
|
+
for (const z of zs) {
|
|
71
|
+
z.l++;
|
|
72
|
+
z.y -= 0.15;
|
|
73
|
+
z.x += 0.1;
|
|
74
|
+
}
|
|
75
|
+
zs = zs.filter((z) => z.l < 20);
|
|
76
|
+
weed += 0.4;
|
|
77
|
+
if (weed > SHORE + 6)
|
|
78
|
+
weed = -30 - r() * 40;
|
|
79
|
+
for (const b of birds) {
|
|
80
|
+
b.x -= 0.25;
|
|
81
|
+
if (b.x < -4) {
|
|
82
|
+
b.x = W + r() * 20;
|
|
83
|
+
b.y = 1 + Math.floor(r() * 3);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
draw(c) {
|
|
88
|
+
drawCloud(c, t, 0.04, 30, 0);
|
|
89
|
+
for (let x = 0; x < SHORE; x++)
|
|
90
|
+
c.set(x, WATER_Y, '▀', 'soil');
|
|
91
|
+
soil.forEach((l, i) => c.put(0, WATER_Y + 1 + i, l, 'soil'));
|
|
92
|
+
for (let y = WATER_Y; y < H; y++) {
|
|
93
|
+
for (let x = SHORE; x < W; x++) {
|
|
94
|
+
const v = (x + y * 3 + Math.floor(t / 3)) % 7;
|
|
95
|
+
c.put(x, y, y === WATER_Y ? (v < 3 ? '~' : '-') : v === 0 ? '~' : ' ', 'water');
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
c.sprite(1, WATER_Y - 7, TREE, 'leaf');
|
|
99
|
+
c.put(4, WATER_Y - 3, '||', 'wood');
|
|
100
|
+
c.put(4, WATER_Y - 2, '||', 'wood');
|
|
101
|
+
c.put(4, WATER_Y - 1, '||', 'wood');
|
|
102
|
+
c.put(7, WATER_Y - 2, ' .-.____ ', 'agent');
|
|
103
|
+
c.put(7, WATER_Y - 1, '(-.-_____)', 'agent');
|
|
104
|
+
for (const z of zs)
|
|
105
|
+
c.put(z.x, z.y, z.l < 8 ? 'z' : 'Z', 'cloud');
|
|
106
|
+
if (weed > -3)
|
|
107
|
+
c.put(weed, WATER_Y - 1, '@', 'dirt');
|
|
108
|
+
for (let x = DOCK_L; x <= DOCK_R; x++)
|
|
109
|
+
c.put(x, WATER_Y - 1, '=', 'wood');
|
|
110
|
+
for (const px of [DOCK_L + 3, DOCK_R - 2])
|
|
111
|
+
for (let y = WATER_Y; y < H - 1; y++)
|
|
112
|
+
c.put(px, y, '|', 'wood');
|
|
113
|
+
c.put(FISHER_X - 7, WATER_Y - 2, '\\_/', 'rock');
|
|
114
|
+
if (fish)
|
|
115
|
+
c.put(FISHER_X - 6, WATER_Y - 3, '>', 'water');
|
|
116
|
+
const face = happy ? (catchKind === 'fish' ? '^.^' : '-_-') : phase === 'bite' ? 'O.O' : blink(t, 1);
|
|
117
|
+
const pulling = phase === 'pull';
|
|
118
|
+
c.sprite(FISHER_X, WATER_Y - 4, withFace(pulling ? SIT_PULL : SIT_ROD, face), 'agent');
|
|
119
|
+
if (pulling) {
|
|
120
|
+
c.put(FISHER_X + 5, WATER_Y - 6, '|', 'wood');
|
|
121
|
+
c.put(FISHER_X + 5, WATER_Y - 7, '.', 'wood');
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
c.put(FISHER_X + 6, WATER_Y - 5, '/', 'wood');
|
|
125
|
+
c.put(FISHER_X + 7, WATER_Y - 6, '/', 'wood');
|
|
126
|
+
c.put(FISHER_X + 8, WATER_Y - 7, '.', 'wood');
|
|
127
|
+
for (let y = WATER_Y - 6; y < WATER_Y; y++)
|
|
128
|
+
c.put(FISHER_X + 9, y, ':', 'cloud');
|
|
129
|
+
const bob = phase === 'bite' ? (t % 4 < 2 ? 1 : 0) : Math.floor(t / 8) % 2 ? 0 : 0;
|
|
130
|
+
c.put(FISHER_X + 9, WATER_Y + bob, 'o', 'fire');
|
|
131
|
+
if (phase === 'bite') {
|
|
132
|
+
c.put(FISHER_X + 8, WATER_Y, '(', 'water');
|
|
133
|
+
c.put(FISHER_X + 10, WATER_Y, ')', 'water');
|
|
134
|
+
c.put(FISHER_X + 1, WATER_Y - 6, '!', 'spark');
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
if (flying)
|
|
138
|
+
c.put(flying.x, flying.y, flying.ch, flying.tone);
|
|
139
|
+
if (happy && t % 6 < 4)
|
|
140
|
+
c.put(FISHER_X - 2, WATER_Y - 6, catchKind === 'fish' ? '(uno más!)' : '(una bota?)', 'cloud');
|
|
141
|
+
for (const b of birds)
|
|
142
|
+
c.put(b.x, b.y, Math.floor(t / 4) % 2 ? 'v' : '-v-', 'cloud');
|
|
143
|
+
},
|
|
144
|
+
status() {
|
|
145
|
+
return `sin tareas pendientes · peces ${fish} · botas ${boots}`;
|
|
146
|
+
},
|
|
147
|
+
};
|
|
148
|
+
},
|
|
149
|
+
};
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-non-null-assertion, prefer-const -- scene arrays are indexed within bounds; particle arrays are mutated in place. */
|
|
2
|
+
import { blink, drawCloud, drawGround, rng, soilLine, withFace } from '../engine.js';
|
|
3
|
+
const W = 78;
|
|
4
|
+
const H = 13;
|
|
5
|
+
const G = 11;
|
|
6
|
+
const HOUSE_X = 60;
|
|
7
|
+
const PASS = [8, 15, 22, 29, 36, 43];
|
|
8
|
+
const THROWER = 50;
|
|
9
|
+
const REACH_L = [' .-. ', ' (o.o)', '_( )', " ' ' "];
|
|
10
|
+
const REACH_R = [' .-. ', '(o.o) ', '( )_', " ' ' "];
|
|
11
|
+
const THROW = [' .-. /', '(o.o)/ ', '( ) ', " ' ' "];
|
|
12
|
+
const WELL = [' ___ ', ' /___\\ ', ' | | ', ' [ ] ', ' [___] '];
|
|
13
|
+
const HOUSE = [' ____ ', ' / \\ ', ' /______\\ ', ' |[] []| ', ' | __ | ', ' |_| |_| '];
|
|
14
|
+
export const fire = {
|
|
15
|
+
id: 'fire',
|
|
16
|
+
title: 'Apagando incendio',
|
|
17
|
+
useFor: 'Tareas urgentes / incidente crítico',
|
|
18
|
+
width: W,
|
|
19
|
+
height: H,
|
|
20
|
+
create(seed = 5) {
|
|
21
|
+
const r = rng(seed);
|
|
22
|
+
const soil = [soilLine(W, r)];
|
|
23
|
+
let t = 0;
|
|
24
|
+
let I = 10;
|
|
25
|
+
let outT = 0;
|
|
26
|
+
let throwT = 0;
|
|
27
|
+
let thrown = 0;
|
|
28
|
+
let buckets = [];
|
|
29
|
+
let water = [];
|
|
30
|
+
let smoke = [];
|
|
31
|
+
let flames = [];
|
|
32
|
+
return {
|
|
33
|
+
step() {
|
|
34
|
+
t++;
|
|
35
|
+
if (t % 16 === 0)
|
|
36
|
+
buckets.push({ x: 6 });
|
|
37
|
+
for (const b of buckets)
|
|
38
|
+
b.x += 0.5;
|
|
39
|
+
if (buckets.length && buckets[0].x >= THROWER - 1) {
|
|
40
|
+
buckets.shift();
|
|
41
|
+
if (I > 0) {
|
|
42
|
+
throwT = 8;
|
|
43
|
+
thrown++;
|
|
44
|
+
for (let i = 0; i < 6; i++) {
|
|
45
|
+
water.push({ x: THROWER + 6, y: G - 4, vx: 0.75 + r() * 0.35, vy: -0.55 - r() * 0.25, ch: "'.:"[i % 3], tone: 'water' });
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
if (throwT)
|
|
50
|
+
throwT--;
|
|
51
|
+
for (const p of water) {
|
|
52
|
+
p.x += p.vx;
|
|
53
|
+
p.y += p.vy;
|
|
54
|
+
p.vy += 0.1;
|
|
55
|
+
}
|
|
56
|
+
water = water.filter((p) => {
|
|
57
|
+
if (p.x >= HOUSE_X + 2 && p.x <= HOUSE_X + 12 && I > 0) {
|
|
58
|
+
I = Math.max(0, I - 0.25);
|
|
59
|
+
smoke.push({ x: p.x, y: p.y, l: 0, steam: true });
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
return p.y < G && p.x < W;
|
|
63
|
+
});
|
|
64
|
+
if (I > 0) {
|
|
65
|
+
I = Math.min(10, I + 0.03);
|
|
66
|
+
outT = 0;
|
|
67
|
+
if (t % 3 === 0)
|
|
68
|
+
smoke.push({ x: HOUSE_X + 2 + r() * 8, y: G - 2 - I * 0.6, l: 0 });
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
outT++;
|
|
72
|
+
if (outT < 40 && t % 4 === 0)
|
|
73
|
+
smoke.push({ x: HOUSE_X + 2 + r() * 8, y: G - 2, l: 0 });
|
|
74
|
+
if (outT > 70)
|
|
75
|
+
I = 2;
|
|
76
|
+
}
|
|
77
|
+
for (const s of smoke) {
|
|
78
|
+
s.l++;
|
|
79
|
+
s.y -= 0.2;
|
|
80
|
+
s.x += 0.1 + Math.sin((s.l + s.x) * 0.4) * 0.1;
|
|
81
|
+
}
|
|
82
|
+
smoke = smoke.filter((s) => s.l < (s.steam ? 8 : 26) && s.y > -1);
|
|
83
|
+
flames = [];
|
|
84
|
+
for (let col = 0; col < 10; col++) {
|
|
85
|
+
flames.push(Math.max(0, Math.round(I * 0.7 * (0.55 + 0.45 * Math.sin(t * 0.7 + col * 1.3)) + (r() - 0.5) * 1.4)));
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
draw(c) {
|
|
89
|
+
drawCloud(c, t, 0.05, 0, 0);
|
|
90
|
+
drawGround(c, G, soil);
|
|
91
|
+
c.sprite(0, G - 5, WELL, 'rock');
|
|
92
|
+
c.put(2, G - 2, '~~~', 'water');
|
|
93
|
+
c.sprite(HOUSE_X, G - 6, HOUSE, 'wood');
|
|
94
|
+
if (I > 0) {
|
|
95
|
+
flames.forEach((h, col) => {
|
|
96
|
+
const x = HOUSE_X + 2 + col;
|
|
97
|
+
for (let k = 0; k < h; k++) {
|
|
98
|
+
const top = k === h - 1;
|
|
99
|
+
const ch = top ? "^'^"[(t + x) % 3] : k < 2 ? 'wWw'[(t + x + k) % 3] : ')(('[(t + x + k) % 3];
|
|
100
|
+
c.put(x, G - 1 - k, ch, top || k > h * 0.6 ? 'flame' : 'fire');
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
const hot = I > 6;
|
|
105
|
+
const out = I <= 0;
|
|
106
|
+
PASS.forEach((x, i) => {
|
|
107
|
+
const cx = x + 2.5;
|
|
108
|
+
const b = buckets.find((b) => b.x + 1.5 > cx - 6 && b.x + 1.5 < cx + 4);
|
|
109
|
+
const pose = b && b.x + 1.5 < cx ? REACH_L : REACH_R;
|
|
110
|
+
c.sprite(x, G - 4, withFace(pose, out ? '^.^' : hot ? blink(t, i, '>.<') : blink(t, i)), 'agent');
|
|
111
|
+
});
|
|
112
|
+
for (const b of buckets) {
|
|
113
|
+
c.put(b.x, G - 2, '\\_/', 'rock');
|
|
114
|
+
c.put(b.x + 1, G - 3, '~', 'water');
|
|
115
|
+
}
|
|
116
|
+
c.sprite(THROWER, G - 4, withFace(throwT > 3 ? THROW : REACH_R, out ? '^.^' : hot ? '>.<' : blink(t, 9)), 'agent');
|
|
117
|
+
if (throwT > 3)
|
|
118
|
+
c.put(THROWER + 6, G - 5, '\\~/', 'water');
|
|
119
|
+
if (hot && Math.floor(t / 20) % 2)
|
|
120
|
+
c.put(7, G - 5, '(agua!)', 'cloud');
|
|
121
|
+
if (out) {
|
|
122
|
+
c.put(14, G - 5, '(uf!)', 'cloud');
|
|
123
|
+
c.put(35, G - 5, '(listo)', 'cloud');
|
|
124
|
+
if (t % 10 < 6)
|
|
125
|
+
c.put(HOUSE_X + 5, G - 8, 'ok', 'good');
|
|
126
|
+
}
|
|
127
|
+
for (const p of water)
|
|
128
|
+
c.put(p.x, p.y, p.ch, p.tone);
|
|
129
|
+
for (const s of smoke)
|
|
130
|
+
c.put(s.x, s.y, s.steam ? '~' : s.l < 8 ? '.' : s.l < 16 ? 'o' : 'O', 'cloud');
|
|
131
|
+
},
|
|
132
|
+
status() {
|
|
133
|
+
const lv = Math.ceil(I / 2);
|
|
134
|
+
return `fuego ${'▮'.repeat(lv)}${'▯'.repeat(5 - lv)} · baldes ${thrown}${I <= 0 ? ' · apagado' : ''}`;
|
|
135
|
+
},
|
|
136
|
+
};
|
|
137
|
+
},
|
|
138
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { working } from './working.js';
|
|
2
|
+
import { resting } from './resting.js';
|
|
3
|
+
import { clockIn } from './clockIn.js';
|
|
4
|
+
import { planning } from './planning.js';
|
|
5
|
+
import { fire } from './fire.js';
|
|
6
|
+
import { celebrate } from './celebrate.js';
|
|
7
|
+
import { syncing } from './syncing.js';
|
|
8
|
+
import { bugHunt } from './bugHunt.js';
|
|
9
|
+
import { empty } from './empty.js';
|
|
10
|
+
import { deadline } from './deadline.js';
|
|
11
|
+
import { cleaning } from './cleaning.js';
|
|
12
|
+
export const SCENES = {
|
|
13
|
+
working,
|
|
14
|
+
resting,
|
|
15
|
+
clockIn,
|
|
16
|
+
planning,
|
|
17
|
+
fire,
|
|
18
|
+
celebrate,
|
|
19
|
+
syncing,
|
|
20
|
+
bugHunt,
|
|
21
|
+
empty,
|
|
22
|
+
deadline,
|
|
23
|
+
cleaning,
|
|
24
|
+
};
|
|
25
|
+
export const SCENE_IDS = Object.keys(SCENES);
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-non-null-assertion -- scene arrays are indexed within their declared bounds. */
|
|
2
|
+
import { blink, drawGround, rng, soilLine, withFace } from '../engine.js';
|
|
3
|
+
const W = 78;
|
|
4
|
+
const H = 12;
|
|
5
|
+
const G = 10;
|
|
6
|
+
const BX = 46;
|
|
7
|
+
const VALS = [3, 3, 3, 2, 3, 2, 2, 2, 1, 2, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0];
|
|
8
|
+
const IDEAS = ['( ? )', '( ! )', '(...)', '( % )', '(ok!)'];
|
|
9
|
+
const SEATED = [' .-. ', '(o.o)', '( )'];
|
|
10
|
+
const POINT_UP = [' .-. ', '(o.o) /', '( )/ ', " ' ' "];
|
|
11
|
+
const POINT_SIDE = [' .-. ', '(o.o) ', '( )--', " ' ' "];
|
|
12
|
+
export const planning = {
|
|
13
|
+
id: 'planning',
|
|
14
|
+
title: 'Analizando planes',
|
|
15
|
+
useFor: 'Planificación / revisión de sprint',
|
|
16
|
+
width: W,
|
|
17
|
+
height: H,
|
|
18
|
+
create(seed = 4) {
|
|
19
|
+
const r = rng(seed);
|
|
20
|
+
const soil = [soilLine(W, r)];
|
|
21
|
+
let t = 0;
|
|
22
|
+
const cycle = () => Math.floor(t / 3) % (VALS.length + 20);
|
|
23
|
+
return {
|
|
24
|
+
step() {
|
|
25
|
+
t++;
|
|
26
|
+
},
|
|
27
|
+
draw(c) {
|
|
28
|
+
drawGround(c, G, soil);
|
|
29
|
+
c.put(BX, 0, ' ' + '_'.repeat(30), 'rock');
|
|
30
|
+
for (let y = 1; y < 7; y++)
|
|
31
|
+
c.put(BX, y, '|' + ' '.repeat(30) + '|', 'rock');
|
|
32
|
+
c.put(BX, 7, '|' + '_'.repeat(30) + '|', 'rock');
|
|
33
|
+
c.put(BX + 4, 8, '/', 'rock');
|
|
34
|
+
c.put(BX + 3, 9, '/', 'rock');
|
|
35
|
+
c.put(BX + 27, 8, '\\', 'rock');
|
|
36
|
+
c.put(BX + 28, 9, '\\', 'rock');
|
|
37
|
+
c.put(BX + 2, 1, 'plan v2', 'text');
|
|
38
|
+
for (let y = 2; y < 6; y++)
|
|
39
|
+
c.put(BX + 3, y, '|', 'cloud');
|
|
40
|
+
c.put(BX + 3, 6, '+' + '-'.repeat(26), 'cloud');
|
|
41
|
+
const n = cycle();
|
|
42
|
+
const done = n >= VALS.length;
|
|
43
|
+
const shown = Math.min(n, VALS.length);
|
|
44
|
+
for (let i = 0; i < shown; i++)
|
|
45
|
+
c.put(BX + 5 + i, 2 + VALS[i], i === shown - 1 ? '*' : '.', 'accent');
|
|
46
|
+
if (done && t % 10 < 6)
|
|
47
|
+
c.put(BX + 30, 1, '!', 'good');
|
|
48
|
+
[11, 20, 29].forEach((x, i) => {
|
|
49
|
+
const face = done ? '^.^' : i === 1 ? blink(t, 7, '-.o') : blink(t, 8 + i);
|
|
50
|
+
c.sprite(x, G - 6, withFace(SEATED, face), 'agent');
|
|
51
|
+
if (Math.floor((t + i * 17) / 22) % 3 < 2) {
|
|
52
|
+
c.put(x - 1, G - 8, IDEAS[(Math.floor(t / 66) + i) % 5], 'cloud');
|
|
53
|
+
c.put(x + 3, G - 7, 'o', 'cloud');
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
c.put(16, G - 4, 'c[]', 'paper');
|
|
57
|
+
c.put(17 + ((t >> 3) % 2), G - 5, '~', 'cloud');
|
|
58
|
+
c.put(25, G - 4, '[=]', 'accent');
|
|
59
|
+
c.put(8, G - 3, '▄'.repeat(31), 'wood');
|
|
60
|
+
for (const lx of [9, 36]) {
|
|
61
|
+
c.put(lx, G - 2, '||', 'wood');
|
|
62
|
+
c.put(lx, G - 1, '||', 'wood');
|
|
63
|
+
}
|
|
64
|
+
const pose = Math.floor(t / 20) % 2 ? POINT_UP : POINT_SIDE;
|
|
65
|
+
c.sprite(39, G - 4, withFace(pose, done ? '^.^' : blink(t, 11)), 'agent');
|
|
66
|
+
},
|
|
67
|
+
status() {
|
|
68
|
+
const n = cycle();
|
|
69
|
+
return n >= VALS.length ? 'plan aprobado' : `analizando · ${Math.round((n / VALS.length) * 100)}%`;
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
},
|
|
73
|
+
};
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { AGENT, blink, drawCloud, drawGround, mirror, rng, soilLine, withFace } from '../engine.js';
|
|
2
|
+
const W = 78;
|
|
3
|
+
const H = 12;
|
|
4
|
+
const G = 10;
|
|
5
|
+
const TREE = [' .--~~--. ', ' .( ~ ~ ). ', '( ~ ~ ~ )', " '-.______.-' "];
|
|
6
|
+
const STRETCH = ['\\ .-. /', ' (o.O) ', ' ( ) ', " ' ' "];
|
|
7
|
+
const COFFEE = [' .-. ', '(o.o)c[]', '(___) '];
|
|
8
|
+
export const resting = {
|
|
9
|
+
id: 'resting',
|
|
10
|
+
title: 'Descansando',
|
|
11
|
+
useFor: 'Sin actividad / en pausa',
|
|
12
|
+
width: W,
|
|
13
|
+
height: H,
|
|
14
|
+
create(seed = 2) {
|
|
15
|
+
const r = rng(seed);
|
|
16
|
+
const soil = [soilLine(W, r)];
|
|
17
|
+
let t = 0;
|
|
18
|
+
let zs = [];
|
|
19
|
+
let leaves = [];
|
|
20
|
+
return {
|
|
21
|
+
step() {
|
|
22
|
+
t++;
|
|
23
|
+
const sw = Math.floor(t / 10) % 2;
|
|
24
|
+
if (t % 14 === 0)
|
|
25
|
+
zs.push({ x: 11, y: G - 3, l: 0 });
|
|
26
|
+
if (t % 18 === 5)
|
|
27
|
+
zs.push({ x: 39 + sw, y: G - 6, l: 0 });
|
|
28
|
+
if (t % 25 === 0)
|
|
29
|
+
leaves.push({ x: 1 + r() * 11, y: 5 });
|
|
30
|
+
for (const z of zs) {
|
|
31
|
+
z.l++;
|
|
32
|
+
z.y -= 0.15;
|
|
33
|
+
z.x += 0.12;
|
|
34
|
+
}
|
|
35
|
+
zs = zs.filter((z) => z.l < 22);
|
|
36
|
+
for (const l of leaves) {
|
|
37
|
+
l.y += 0.12;
|
|
38
|
+
l.x += Math.sin(l.y * 2) * 0.3;
|
|
39
|
+
}
|
|
40
|
+
leaves = leaves.filter((l) => l.y < G - 0.5);
|
|
41
|
+
},
|
|
42
|
+
draw(c) {
|
|
43
|
+
drawCloud(c, t, 0.05, 10, 0);
|
|
44
|
+
drawGround(c, G, soil);
|
|
45
|
+
c.put(73, 0, '\\ | /', 'spark');
|
|
46
|
+
c.put(73, 1, '- O -', 'spark');
|
|
47
|
+
c.put(73, 2, '/ | \\', 'spark');
|
|
48
|
+
c.sprite(0, 2, TREE, 'leaf');
|
|
49
|
+
for (let y = 6; y < G; y++)
|
|
50
|
+
c.put(6, y, '||', 'wood');
|
|
51
|
+
c.put(10, G - 2, ' .-.____ ', 'agent');
|
|
52
|
+
c.put(10, G - 1, '(-.-_____)', 'agent');
|
|
53
|
+
const sip = t % 50 < 8;
|
|
54
|
+
c.sprite(21, G - 3, withFace(COFFEE, sip ? '^.^' : blink(t, 1)), 'agent');
|
|
55
|
+
c.put(26, G - 2, 'c[]', 'paper');
|
|
56
|
+
c.put(27 + ((t >> 3) % 2), G - 3, '~', 'cloud');
|
|
57
|
+
const sw = Math.floor(t / 10) % 2;
|
|
58
|
+
for (let y = G - 5; y < G; y++) {
|
|
59
|
+
c.put(33, y, '|', 'wood');
|
|
60
|
+
c.put(49, y, '|', 'wood');
|
|
61
|
+
}
|
|
62
|
+
c.put(34, G - 4, '\\', 'wood');
|
|
63
|
+
c.put(48, G - 4, '/', 'wood');
|
|
64
|
+
c.put(35, G - 3, '\\___________/', 'wood');
|
|
65
|
+
c.put(38 + sw, G - 5, ' .-.___', 'agent');
|
|
66
|
+
c.put(38 + sw, G - 4, '(-.-___)', 'agent');
|
|
67
|
+
if (Math.floor(t / 24) % 3 === 0)
|
|
68
|
+
c.sprite(53, G - 4, STRETCH, 'agent');
|
|
69
|
+
else
|
|
70
|
+
c.sprite(54, G - 4, withFace(AGENT.stand, blink(t, 2)), 'agent');
|
|
71
|
+
const ph = Math.floor(t / 15) % 4;
|
|
72
|
+
c.sprite(62, G - 3, withFace(AGENT.sit, blink(t, 3)), 'agent');
|
|
73
|
+
c.sprite(68, G - 3, withFace(mirror(AGENT.sit), ph === 1 ? '^.^' : blink(t, 4)), 'agent');
|
|
74
|
+
if (ph === 0)
|
|
75
|
+
c.put(61, G - 4, '(bla)', 'cloud');
|
|
76
|
+
if (ph === 1)
|
|
77
|
+
c.put(67, G - 4, '(jaja)', 'cloud');
|
|
78
|
+
if (ph === 2)
|
|
79
|
+
c.put(61, G - 4, '(...)', 'cloud');
|
|
80
|
+
for (const z of zs)
|
|
81
|
+
c.put(z.x, z.y, z.l < 8 ? 'z' : 'Z', 'cloud');
|
|
82
|
+
for (const l of leaves)
|
|
83
|
+
c.put(l.x, l.y, ',', 'leaf');
|
|
84
|
+
},
|
|
85
|
+
status() {
|
|
86
|
+
return 'en pausa · recargando energía';
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
},
|
|
90
|
+
};
|