summaryrefslogtreecommitdiff
path: root/src/BCDDFile.cs
blob: 03d0af280cc82eadc9bda4d7aa7e456ee4e7648b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
using System;
using System.Collections.Generic;
using System.Threading;

namespace BCDD
{
    public class BCDDFile
    {
        public List<String> errors;
        private String filename;
        private PBNFile file;
        private String shortname;

        public static int filesCounter;
        public static ManualResetEvent filesCountdown = new ManualResetEvent(false);

        private int boardCount;
        private ManualResetEvent boardCountdown;

        public BCDDFile(String filename)
        {
            this.errors = new List<String>();
            this.filename = filename;
            this.file = new PBNFile(filename);
            this.shortname = Path.GetFileName(this.filename);
            if (this.file.ParseErrors.Count > 0)
            {
                this.error("PBN format errors encountered");
                foreach (KeyValuePair<int, String> kv in this.file.ParseErrors)
                {
                    this.error(kv.Value, "", kv.Key);
                }
            }
        }

        private void error(String message, String boardNo = "", int lineNo = -1)
        {
            if (!"".Equals(boardNo))
            {
                message = String.Format("[{0}:B#{1}] {2}", this.shortname, boardNo, message);
            }
            else if (lineNo > -1)
            {
                message = String.Format("[{0}:L#{1}] {2}", this.shortname, lineNo, message);
            }
            else
            {
                message = String.Format("[{0}] {1}", this.shortname, message);
            }
            errors.Add(message);
            Console.WriteLine("ERROR: " + message);
        }

        private void info(String boardNo, String ddTable, ParContract contract)
        {
            Console.WriteLine(String.Format("[{0}:{1}] {2} {3}", this.shortname, boardNo, ddTable, contract));
        }

        private void processBoard(object state)
        {
            PBNBoard board = state as PBNBoard;
            DDTable table = new DDTable(board);
            String boardNo;
            try
            {
                boardNo = board.GetNumber();
            }
            catch (FieldNotFoundException)
            {
                boardNo = "?";
            }
            try
            {
                List<String> validationErrors = board.ValidateLayout();
                if (validationErrors.Count > 0)
                {
                    throw new InvalidLayoutException(
                        String.Join("; ", validationErrors.ToArray())
                    );
                }
                int[,] ddTable = table.GetDDTable();
                if (ddTable != null)
                {
                    ParScore par = new ParScore(board);
                    ParContract contract = par.GetParContract(ddTable);
                    board.SaveDDTable(ddTable);
                    board.SaveParContract(contract);
                    this.info(boardNo, DDTable.ShortFormat(ddTable), contract);
                }
                else
                {
                    this.error("unable to determine DD table for board " + boardNo, boardNo);
                }
            }
            catch (DllNotFoundException)
            {
                throw;
            }
            catch (Exception e)
            {
                this.error(e.Message, boardNo);
            }
            finally
            {
                if (Interlocked.Decrement(ref this.boardCount) == 0)
                {
                    this.boardCountdown.Set();
                }
            }
        }

        public void analyze(object state)
        {
            try
            {
                this.boardCount = this.file.Boards.Count;
                this.boardCountdown = new ManualResetEvent(false);
                foreach (PBNBoard board in this.file.Boards)
                {
                    ThreadPool.QueueUserWorkItem(new WaitCallback(this.processBoard), board);
                }
                boardCountdown.WaitOne();
            }
            catch (DllNotFoundException)
            {
                this.error("libbcalcdds.dll could not be loaded - make sure it's present in application directory!");
                return;
            }
            catch (Exception e)
            {
                this.error(e.Message);
            }
            finally
            {
                foreach (PBNBoard board in this.file.Boards) {
                    this.file.WriteBoard(board);
                }
                Console.WriteLine(String.Format("Saving file {0}", this.filename));
                this.file.Save();
                if (Interlocked.Decrement(ref BCDDFile.filesCounter) == 0)
                {
                    BCDDFile.filesCountdown.Set();
                }
            }
        }
    }
}