Пример #1
0
        // game logic
        private void StartNextRound()
        {
            if (IsDone)
            {
                try
                {
                    LibraryLock.EnterWriteLock();

                    // reset the stats
                    Stats.Reset();
                    lock (Ephemerials)
                    {
                        Ephemerials.Clear();
                    }

                    // prepare a new poem
                    CurrentLine = 0;
                    CurrentBook = Library.Randomize();
                    CurrentPoem = Library.Randomize(CurrentBook);
                    var stanza = Library.Randomize(CurrentPoem, maxChars: 100, maxCharsPerLine: 20);
                    Lines = new Line[stanza.Count];
                    // construct the lines
                    var lengths = new int[stanza.Count];
                    for (int i = 0; i < Lines.Length; i++)
                    {
                        Lines[i]   = new Line(i, stanza[i]);
                        lengths[i] = Lines[i].Text.Length;
                    }

                    // reset
                    Cat.Reset(lengths, xStart: TextXStart, yStart: TextYStart + (TextSpacing * 5) - (Cat.Height * 0.75f), xDelta: FontWidth, yDelta: TextSpacing);
                    IsDone = false;
                }
                finally
                {
                    LibraryLock.ExitWriteLock();
                }
            }
        }
Пример #2
0
        public List <string> Randomize(Poem poem, int maxChars, int maxCharsPerLine)
        {
            // pick a random set of lines within this poem
            if (poem == null || poem.Lines.Count == 0 || maxChars <= 0 || maxCharsPerLine <= 0)
            {
                throw new Exception("Must provide a valid poem");
            }

            var lines = new List <string>();
            var start = 0;

            // get all the lengths so that a random start can be calculated
            // get the index of which we can still satisfy the 'maxChars' requirement
            // determine a random starting index
            var lengthSum = 0;

            for (int i = poem.Lines.Count - 1; i >= 0; i--)
            {
                lengthSum += poem.Lines[i].Length;
                if (lengthSum >= maxChars && i > 0)
                {
                    start = Random.Next() % i;
                    break;
                }
            }

            // grab 'maxChars' from the poem with a local maximum of 'maxCharsPerLine'
            lengthSum = maxChars;
            for (int i = start; lengthSum > 0 && i < poem.Lines.Count; i++)
            {
                var text = poem.Lines[i];
                if (lengthSum - poem.Lines[i].Length < 0)
                {
                    // this is the last line and it is too long
                    var length = lengthSum;
                    // find the end of the current word
                    while (length < text.Length && text[length] != ' ')
                    {
                        length++;
                    }
                    text = poem.Lines[i].Substring(0, length);
                }

                // add lines that do not exceed 'maxCharsPerLine'
                var index = 0;
                while (index < text.Length)
                {
                    var length = (text.Length - index) > maxCharsPerLine ? maxCharsPerLine : (text.Length - index);
                    // ensure to break on a space
                    while ((index + length) > 0 && (index + length) != text.Length && text[index + length - 1] != ' ')
                    {
                        length--;
                    }
                    if (length <= 0)
                    {
                        throw new Exception("Failed to find a space");
                    }
                    lines.Add(text.Substring(index, length).Trim());
                    index += length;
                }

                lengthSum -= poem.Lines[i].Length;
            }

            return(lines);
        }
Пример #3
0
        public static Book ParseMd(string[] lines)
        {
            // spec:
            //   <head>
            //   #Title: Title
            //   #Author: Author
            //   </head>
            //   <book>
            //   ' comment
            //   #Section Header
            //   #Name
            //   </book>
            // transforms:
            //   remove:
            //      {...}, [...] (may be multiline, and more than 1 per line)
            //      completely whitespace
            //      leading and trailing whitespace
            //      numbers (eg. line numbers)
            //   replace:
            //      ’, “, ”, &mdash;, è, _

            var book            = new Book();
            var poems           = new Dictionary <string /*section*/, Dictionary <string /*title*/, Poem> >();
            var delineators     = new Tuple <char, char>[] { new Tuple <char, char>('{', '}'), new Tuple <char, char>('[', ']') };
            var state           = ParseState.None;
            var section         = "";
            var title           = "";
            var validCharacters = new Regex("^[\\\" -abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789,:;]+$");

            for (int i = 0; i < lines.Length; i++)
            {
                if (string.IsNullOrWhiteSpace(lines[i]))
                {
                    continue;
                }

                // trim leading and trailing whitespace
                lines[i] = lines[i].Trim();

                // skip comments
                if (lines[i].StartsWith("'"))
                {
                    continue;
                }

                // remove leading numbers
                var index = -1;
                while ((index + 1) < lines[i].Length && char.IsDigit(lines[i][index + 1]))
                {
                    index++;
                }
                if (index >= 0)
                {
                    lines[i] = lines[i].Substring(index + 1).Trim();
                }

                // check state
                if (lines[i].Equals("<head>", StringComparison.OrdinalIgnoreCase))
                {
                    state = ParseState.Head; continue;
                }
                else if (lines[i].Equals("</head>", StringComparison.OrdinalIgnoreCase))
                {
                    state = ParseState.None;
                }
                else if (lines[i].Equals("<book>", StringComparison.OrdinalIgnoreCase))
                {
                    state = ParseState.Book; continue;
                }
                else if (lines[i].Equals("</book>", StringComparison.OrdinalIgnoreCase))
                {
                    state = ParseState.None;
                }

                if (state == ParseState.None)
                {
                    continue;
                }

                // transform
                lines[i] = lines[i].Replace("’", "'")
                           .Replace("‘", "'")
                           .Replace("“", "\"")
                           .Replace("”", "\"")
                           .Replace("  ", " ")
                           .Replace("&mdash;", "-")
                           .Replace("_", " ")
                           .Replace("è", "e")
                           .Replace("á", "a")
                           .Replace("ü", "u")
                           .Replace("ē", "e")
                           .Replace("é", "e")
                           .Replace("æ", "a");

                // remove {...} [...]
                foreach (var m in delineators)
                {
                    // find the start and end of these delineators
                    var lineStart = -1;
                    var lineEnd   = -1;
                    var start     = lines[i].IndexOf(m.Item1);
                    var end       = -1;
                    var escape    = 10;
                    while (start >= 0)
                    {
                        lineStart = lineEnd = i;
                        // find the end
                        do
                        {
                            end = lines[lineEnd].IndexOf(m.Item2);
                            if (end < 0)
                            {
                                lineEnd++;
                            }
                        }while (end < 0 && lineEnd < lines.Length && --escape >= 0);

                        // hit the limit
                        if (escape == 0)
                        {
                            throw new Exception("Failed to find closing delineator");
                        }

                        // single line remove
                        if (lineEnd == i)
                        {
                            var line = "";
                            if (start > 0)
                            {
                                line = lines[i].Substring(0, start - 1);
                            }
                            if ((end + 1) < lines[i].Length)
                            {
                                line += lines[i].Substring(end + 1);
                            }
                            lines[i] = line.Trim();
                        }
                        // multi-line
                        else
                        {
                            // first line
                            if (start > 0)
                            {
                                lines[lineStart] = lines[lineStart].Substring(0, start - 1).TrimEnd();
                            }
                            else
                            {
                                lines[lineStart] = "";
                            }

                            // middlelines
                            lineStart++;
                            while (lineStart < lineEnd)
                            {
                                lines[lineStart++] = "";
                            }

                            // last line
                            if ((end + 1) < lines[lineEnd].Length)
                            {
                                lines[lineEnd] = lines[lineEnd].Substring(end + 1).TrimStart();
                            }
                            else
                            {
                                lines[lineEnd] = "";
                            }
                        }

                        // check again
                        start = lines[i].IndexOf(m.Item1);
                    }
                }

                // remove empty lines
                if (string.IsNullOrWhiteSpace(lines[i]))
                {
                    continue;
                }

                // parse
                if (state == ParseState.Head)
                {
                    if (lines[i].ToLower().StartsWith("#title:"))
                    {
                        book.Title = lines[i].Substring(7).Trim();
                    }
                    else if (lines[i].ToLower().StartsWith("#author:"))
                    {
                        book.Author = lines[i].Substring(8).Trim();
                    }
                }
                else if (state == ParseState.Book)
                {
                    if (lines[i].StartsWith("##"))
                    {
                        title = lines[i].Substring(2).Trim();
                    }
                    else if (lines[i].StartsWith("#"))
                    {
                        section = lines[i].Substring(1).Trim();
                    }
                    else
                    {
                        if (string.IsNullOrWhiteSpace(section) || string.IsNullOrWhiteSpace(title))
                        {
                            throw new Exception("Empty names");
                        }

                        // add poem
                        Dictionary <string, Poem> bySection = null;
                        if (!poems.TryGetValue(section, out bySection))
                        {
                            bySection = new Dictionary <string, Poem>();
                            poems.Add(section, bySection);
                        }
                        Poem poem = null;
                        if (!bySection.TryGetValue(title, out poem))
                        {
                            poem = new Poem()
                            {
                                Section = section, Title = title
                            };
                            bySection.Add(title, poem);
                            book.Poems.Add(poem);
                        }

                        // sanity check the line content
                        if (!validCharacters.IsMatch(lines[i]))
                        {
                            throw new Exception("Failed on : " + lines[i]);
                        }

                        // add lines to the poem
                        poem.Lines.Add(lines[i].Trim());
                    }
                }
                else
                {
                    throw new Exception("Unknown state");
                }
            }

            if (book.Poems.Count == 0)
            {
                throw new Exception("Failed to parse poems");
            }

            return(book);
        }