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 import util; 1 import util;
2 import game; 2 import game;
3 import core.stdc.signal; | 3 import driver;
4 import std.c.stdlib; 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 this(const(Game) g) {}
9 void flush(); | 10 override bool on_game_changed(char c, const(Game) g, bool finished) {ret
10 } 11 }
11 12
12 class NilOutput : Output | 13 class StdOutput : GameObserver
13 { 14 {
14 override void command(char c) {} | 15 this(const(Game) g) {}
15 override void flush() {} | 16 override bool on_game_changed(char c, const(Game) g, bool finished)
16 } <
17 <
18 class StdOutput : Output <
19 { <
20 override void command(char c) <
21 { 17 {
22 write(c); | 18 stdout.write(c);
23 stdout.flush(); 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. | 26 this(const(Game) g)
34 static this() <
> 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) | 42 private:
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 <
52 <
53 string log; 43 string log;
54 long[] score_log; 44 long[] score_log;
55 long[] ideal_log; 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 Tuple!(long, int, int) cand; 49 Tuple!(long, int, int) cand;
67 cand[0] = long.min; 50 cand[0] = long.min;
68 foreach(int i, long s; score_log) <
> 51
> 52 for(int i=0; i<score_log.length; ++i)
69 if(cand[0] < s) | 53 if(cand[0] < score_log[i])
70 cand = tuple(s,i,0); | 54 cand = tuple(score_log[i],i,0);
71 foreach(int i, long s; ideal_log) <
> 55 for(int i=0; i<ideal_log.length; ++i)
72 if(cand[0] < s) | 56 if(cand[0] < ideal_log[i])
73 cand = tuple(s,i,1); | 57 cand = tuple(ideal_log[i],i,1);
> 58
74 if(cand[2]==0) | 59 if(cand[2]==0) {
75 writeln(log[0..cand[1]+1]); | 60 string str = log[0..cand[1]+1];
> 61 std.c.stdio.printf("%.*s\n", str.length, str.ptr);
76 else | 62 } else {
77 writeln(log[0..cand[1]]~"A"); | 63 string str = log[0..cand[1]];
78 stdout.flush(); <
> 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(); appl
> 77 core.stdc.signal.signal(SIGINT, &catch_sigint);
79 } 78 }
80 } 79 }