using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Text.RegularExpressions;
namespace Analizator9000
{
///
/// Parsers dealer script files into fileds used by the application and compiles deler script files from them.
///
class DealerParser
{
///
/// Contents of 'condition' section of dealer input script.
///
public String condition = "";
///
/// Limit of deals to generate, 'generate' section of input script.
///
public long generate = -1;
///
/// Limit of deals to produce, 'produce' section of input script.
///
public long produce = -1;
///
/// Pre-dealt cards, indexed by player. Compiles into 'predeal' section of onput script.
///
public Dictionary predeal = new Dictionary();
///
/// "Actions" for Dealer to the check average value of.
///
public List actions = new List();
///
/// Loads the input script file and parses it. Parses out everything outside of predeal/condition/produce/generate/action sections.
///
/// Filename of the script.
public void loadFile(String file)
{
String[] contents = File.ReadAllLines(file);
Dictionary keyLines = new Dictionary();
String[] keywords = {"predeal", "condition", "generate", "produce", "action"};
for (int i = 0; i < contents.Length; i++)
{
String line = contents[i];
int lineNo = Array.IndexOf(keywords, line.Trim());
if (lineNo >= 0)
{
keyLines.Add(keywords[lineNo], i);
}
}
keyLines = keyLines.OrderBy(x => x.Value).ToDictionary(x => x.Key, x => x.Value);
for (int i = 0; i < keyLines.Count; i++)
{
KeyValuePair keyline = keyLines.ElementAt(i);
String[] section = new String[contents.Length - keyline.Value];
if (i + 1 < keyLines.Count)
{
Array.Copy(contents, keyline.Value, section, 0, keyLines.ElementAt(i + 1).Value - keyline.Value);
}
else
{
Array.Copy(contents, keyline.Value, section, 0, contents.Length - keyline.Value);
}
section[0] = Regex.Replace(section[0], "^"+keyline.Key, "").Trim();
section = section.Where(str => str != null && str.Trim().Length > 0).ToArray();
switch (keyline.Key)
{
case "predeal":
String[] players = { "north", "east", "south", "west" };
char[] suits = { 'S', 'H', 'D', 'C' };
foreach (String l in section)
{
String line = l.Trim();
int player = Array.IndexOf(players, line.Substring(0, line.IndexOf(' ')));
if (player >= 0) {
String[] chunks = Regex.Replace(line, "^" + players[player], "").Split(',');
String[] hand = new String[4];
foreach (String chunk in chunks)
{
int suit = Array.IndexOf(suits, chunk.Trim().ToUpper()[0]);
if (suit >= 0)
{
hand[suit] = chunk.Trim().Substring(1);
}
}
this.predeal.Add(players[player], hand);
}
}
break;
case "condition":
this.condition = section.Aggregate((a, b) => a + "\n" + b);
break;
case "generate":
if (section.Length > 1)
{
throw new Exception(Form1.GetResourceManager().GetString("DealerParser_errorTooManyGenerate", Form1.GetCulture()));
}
if (section.Length == 1)
{
try
{
this.generate = Convert.ToInt64(section[0]);
}
catch (OverflowException)
{
throw new Exception(Form1.GetResourceManager().GetString("DealerParser_errorGenerateOverflow", Form1.GetCulture()));
}
}
break;
case "produce":
if (section.Length > 1)
{
throw new Exception(Form1.GetResourceManager().GetString("DealerParser_errorTooManyProduce", Form1.GetCulture()));
}
if (section.Length == 1)
{
try
{
this.produce = Convert.ToInt64(section[0]);
}
catch (OverflowException)
{
throw new Exception(Form1.GetResourceManager().GetString("DealerParser_errorProduceOverflow", Form1.GetCulture()));
}
}
break;
case "action":
Regex pattern = new Regex(@"(?,)|(?\()|(?\))|(?[^,\(\)]*)");
MatchCollection matches = pattern.Matches(section.Aggregate((a, b) => a + b));
List tokens = new List();
foreach (Match match in matches)
{
int groupNo = 0;
foreach (Group group in match.Groups)
{
if (group.Success && groupNo > 0)
{
tokens.Add(group.Value);
}
groupNo++;
}
}
int open = 0;
List actions = new List();
String currentAction = "";
foreach (String token in tokens)
{
switch (token)
{
case "(":
open++;
currentAction += token;
break;
case ")":
open--;
currentAction += token;
break;
case ",":
if (open == 0)
{
actions.Add(currentAction.Trim());
currentAction = "";
}
else
{
currentAction += token;
}
break;
default:
currentAction += token;
break;
}
}
actions.Add(currentAction.Trim());
this.actions = actions.Where(s => s.StartsWith("average")).ToList();
break;
}
}
}
///
/// Compiles dealer input script from provided data. Assumes no overhead and action "printoneline" on top of all the declared "average" events.
///
/// Input script name.
public String saveFile()
{
if (!Directory.Exists("files"))
{
Directory.CreateDirectory("files");
}
String filename = Utils.getFilename("dealer");
StreamWriter file = new StreamWriter(@"files\" + filename);
String predealStr = "";
String suitLetters = "SHDC";
foreach (KeyValuePair pre in this.predeal)
{
List hand = new List();
for (int i = 0; i < pre.Value.Length; i++)
{
if (pre.Value[i].Trim().Length > 0)
{
hand.Add(suitLetters[i] + pre.Value[i].Trim());
}
}
if (hand.Count > 0)
{
predealStr += pre.Key + " " + hand.Aggregate((a, b) => a + ", " + b) + "\n";
}
}
if (predealStr.Length > 0)
{
file.WriteLine("predeal");
file.Write(predealStr);
}
if (this.condition.Trim().Length > 0)
{
file.WriteLine("condition");
file.WriteLine(this.condition);
}
file.WriteLine("generate");
file.WriteLine(this.generate);
file.WriteLine("produce");
file.WriteLine(this.produce);
file.WriteLine("action");
file.Write("printoneline");
foreach (String action in this.actions)
{
if (action.Trim().Length > 0)
{
file.WriteLine(",");
file.Write("average " + action);
}
}
file.WriteLine();
file.Close();
return filename;
}
}
}