Differences From Artifact [1b458d7cd25e92dc]:
- File
output.d
- 2012-07-14 08:31:35 - part of checkin [a5e6c99b3d] on branch trunk - Guarded. (user: kinaba) [annotate]
- File
src/output.d
- 2012-07-14 09:16:47 - part of checkin [6293256fec] on branch trunk - Preparing for submission... (user: kinaba) [annotate]
To Artifact [2ca374354297c908]:
- File
src/output.d
- 2012-07-14 11:24:30 - part of checkin [bee0596f0f] on branch trunk - Refactoring. (user: kinaba) [annotate]
1 1 import util;
2 2 import game;
3 -import core.stdc.signal;
3 +import driver;
4 4 import std.c.stdlib;
5 +import core.stdc.signal;
5 6
6 -abstract class Output
7 +class NilOutput : GameObserver
7 8 {
8 - void command(char c);
9 - void flush();
9 + this(const(Game) g) {}
10 + override bool on_game_changed(char c, const(Game) g, bool finished) {return false;}
10 11 }
11 12
12 -class NilOutput : Output
13 +class StdOutput : GameObserver
13 14 {
14 - override void command(char c) {}
15 - override void flush() {}
16 -}
17 -
18 -class StdOutput : Output
19 -{
20 - override void command(char c)
15 + this(const(Game) g) {}
16 + override bool on_game_changed(char c, const(Game) g, bool finished)
21 17 {
22 - write(c);
18 + stdout.write(c);
23 19 stdout.flush();
20 + return false;
24 21 }
25 - override void flush() {}
26 22 }
27 23
28 -// TODO: clean it up.
29 -__gshared Output g_output;
30 -
31 -class GuardedOutput : StdOutput
24 +class GuardedOutput : GameObserver
32 25 {
33 - // Handle SIGINT: force abort and exit.
34 - static this()
26 + this(const(Game) g)
27 + {
28 + setup_sigint_handling();
29 + ideal_log ~= g.score_if_abort_now;
30 + }
31 +
32 + override bool on_game_changed(char c, const(Game) g, bool finished)
35 33 {
36 - signal(SIGINT, &sigint);
34 + log ~= c;
35 + score_log ~= g.score;
36 + ideal_log ~= g.score_if_abort_now;
37 + if(finished)
38 + flush();
39 + return false;
37 40 }
38 41
39 - extern(C) static void sigint(int)
40 - {
41 - if(g_output !is null)
42 - g_output.flush();
43 - else {
44 - write("A");
45 - stdout.flush();
46 - }
47 - exit(0);
48 - }
49 -
50 - Game g;
51 - this(Game ini) { this.g = ini.clone(); ideal_log ~= g.score_if_abort_now; g_output = this; }
52 -
42 +private:
53 43 string log;
54 44 long[] score_log;
55 45 long[] ideal_log;
56 46
57 - override void command(char c)
58 - {
59 - g.command(c);
60 - log ~= c;
61 - score_log ~= g.score;
62 - ideal_log ~= g.score_if_abort_now;
63 - }
64 - override void flush()
47 + void flush()
65 48 {
66 49 Tuple!(long, int, int) cand;
67 50 cand[0] = long.min;
68 - foreach(int i, long s; score_log)
69 - if(cand[0] < s)
70 - cand = tuple(s,i,0);
71 - foreach(int i, long s; ideal_log)
72 - if(cand[0] < s)
73 - cand = tuple(s,i,1);
74 - if(cand[2]==0)
75 - writeln(log[0..cand[1]+1]);
76 - else
77 - writeln(log[0..cand[1]]~"A");
78 - stdout.flush();
51 +
52 + for(int i=0; i<score_log.length; ++i)
53 + if(cand[0] < score_log[i])
54 + cand = tuple(score_log[i],i,0);
55 + for(int i=0; i<ideal_log.length; ++i)
56 + if(cand[0] < ideal_log[i])
57 + cand = tuple(ideal_log[i],i,1);
58 +
59 + if(cand[2]==0) {
60 + string str = log[0..cand[1]+1];
61 + std.c.stdio.printf("%.*s\n", str.length, str.ptr);
62 + } else {
63 + string str = log[0..cand[1]];
64 + std.c.stdio.printf("%.*sA\n", str.length, str.ptr);
65 + }
66 + std.c.stdio.fflush(std.c.stdio.stdout);
67 + }
68 +
69 +private:
70 + static __gshared GuardedOutput g_output;
71 +
72 + void setup_sigint_handling()
73 + {
74 + assert(g_output is null);
75 + g_output = this;
76 + extern(C) static void catch_sigint(int) { g_output.flush(); application_exit(); }
77 + core.stdc.signal.signal(SIGINT, &catch_sigint);
79 78 }
80 79 }