<commit_before>﻿using Scripts.Model.Characters;
using Scripts.Model.Pages;
using Scripts.Model.TextBoxes;
using Scripts.Presenter;
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;

namespace Scripts.Model.Acts {

    /// <summary>
    /// Represents an event occurring in the game.
    /// This would be named Event but that class already exists.
    /// Can be chained together using Game's Cutscene method.
    /// </summary>
    public class Act {
        public readonly Action Action;
        public readonly float Delay;
        public readonly Func<bool> HasEnded;
        public readonly bool RequiresUserAdvance;
        public readonly bool IsSkippable;
        public readonly Action SkipAction;

        private const char AVATARBOX_SYMBOL = '/';

        /// <summary>
        /// Splits up a string
        /// "/Hello>World" to "/Hello" and ">World"
        /// </summary>
        private const string REGEX = "(?=>|/)";

        private const char TEXTBOX_SYMBOL = '>';

        public Act(Action a) : this(a, () => true, 0, false) {
        }

        public Act(TextBox t) : this(
            () => Game.Instance.TextBoxes.AddTextBox(t),
            () => {
                t.Effect = TextEffect.FADE_IN;
                Game.Instance.TextBoxes.AddTextBox(t);
            },
            () => t.IsDone,
            0.5f,
            true) {
        }

        public Act(string imageLoc, string text) : this(
            () => Game.Instance.Title.Play(imageLoc, text),
            () => Game.Instance.Title.IsDone, 0.5f, false) {
        }

        public Act(Page nextPage) : this(() => Game.Instance.CurrentPage = nextPage, () => true, 0.5f, false) {
        }

        private Act(Action action, Func<bool> endCondition, float delay, bool reqUserAdv) {
            this.Action = action;
            this.HasEnded = endCondition ?? (() => true);
            this.Delay = delay;
            this.RequiresUserAdvance = reqUserAdv;
            this.IsSkippable = false;
        }

        private Act(Action action, Action skipAction, Func<bool> endCondition, float delay, bool reqUserAdv) {
            this.Action = action;
            this.HasEnded = endCondition ?? (() => true);
            this.Delay = delay;
            this.RequiresUserAdvance = reqUserAdv;
            this.IsSkippable = true;
            this.SkipAction = skipAction;
        }

        public static Act[] LongTalk(Character c, string big) {
            List<Act> events = new List<Act>();
            IList<TextBox> boxes = SplitBigDialogue(c, big);

            for (int i = 0; i < boxes.Count; i++) {
                events.Add(new Act(boxes[i]));
            }
            return events.ToArray();
        }

        /// <summary>
        /// Use regex to split up a long string into an Emotes
        /// and Talks cutscene by a specific character
        /// </summary>
        private static IList<TextBox> SplitBigDialogue(Character c, string big) {
            string[] split = Regex.Split(big, REGEX);
            IList<TextBox> boxes = new List<TextBox>();

            // The 0th index element is "" so skip it
            for (int i = 1; i < split.Length; i++) {
                char front = split[i][0];
                string rest = split[i].Substring(1);
                switch (front) {
                    case TEXTBOX_SYMBOL:
                        boxes.Add(c.Emote(rest));
                        break;

                    case AVATARBOX_SYMBOL:
                        boxes.Add(c.Talk(rest));
                        break;

                    default:
                        Util.Assert(false, "Unknown symbol in front of " + split[i]);
                        break;
                }
            }
            return boxes;
        }
    }
}<commit_msg>This class is also broken due to new character changes.<commit_after>﻿using Scripts.Model.Characters;
using Scripts.Model.Pages;
using Scripts.Model.TextBoxes;
using Scripts.Presenter;
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;

namespace Scripts.Model.Acts {

    /// <summary>
    /// Represents an event occurring in the game.
    /// This would be named Event but that class already exists.
    /// Can be chained together using Game's Cutscene method.
    /// </summary>
    public class Act {
        public readonly Action Action;
        public readonly float Delay;
        public readonly Func<bool> HasEnded;
        public readonly bool RequiresUserAdvance;
        public readonly bool IsSkippable;
        public readonly Action SkipAction;

        private const char AVATARBOX_SYMBOL = '/';

        /// <summary>
        /// Splits up a string
        /// "/Hello>World" to "/Hello" and ">World"
        /// </summary>
        private const string REGEX = "(?=>|/)";

        private const char TEXTBOX_SYMBOL = '>';

        public Act(Action a) : this(a, () => true, 0, false) {
        }

        public Act(TextBox t) : this(
            () => Game.Instance.TextBoxes.AddTextBox(t),
            () => {
                t.Effect = TextEffect.FADE_IN;
                Game.Instance.TextBoxes.AddTextBox(t);
            },
            () => t.IsDone,
            0.5f,
            true) {
        }

        public Act(string imageLoc, string text) : this(
            () => Game.Instance.Title.Play(imageLoc, text),
            () => Game.Instance.Title.IsDone, 0.5f, false) {
        }

        private Act(Action action, Func<bool> endCondition, float delay, bool reqUserAdv) {
            this.Action = action;
            this.HasEnded = endCondition ?? (() => true);
            this.Delay = delay;
            this.RequiresUserAdvance = reqUserAdv;
            this.IsSkippable = false;
        }

        private Act(Action action, Action skipAction, Func<bool> endCondition, float delay, bool reqUserAdv) {
            this.Action = action;
            this.HasEnded = endCondition ?? (() => true);
            this.Delay = delay;
            this.RequiresUserAdvance = reqUserAdv;
            this.IsSkippable = true;
            this.SkipAction = skipAction;
        }

        public static Act[] LongTalk(Character c, string big) {
            List<Act> events = new List<Act>();
            IList<TextBox> boxes = SplitBigDialogue(c, big);

            for (int i = 0; i < boxes.Count; i++) {
                events.Add(new Act(boxes[i]));
            }
            return events.ToArray();
        }

        /// <summary>
        /// Use regex to split up a long string into an Emotes
        /// and Talks cutscene by a specific character
        /// </summary>
        private static IList<TextBox> SplitBigDialogue(Character c, string big) {
            string[] split = Regex.Split(big, REGEX);
            IList<TextBox> boxes = new List<TextBox>();

            // The 0th index element is "" so skip it
            for (int i = 1; i < split.Length; i++) {
                char front = split[i][0];
                string rest = split[i].Substring(1);
                switch (front) {
                    case TEXTBOX_SYMBOL:
                        boxes.Add(c.Emote(rest));
                        break;

                    case AVATARBOX_SYMBOL:
                        //boxes.Add(c.Talk(rest));
                        break;

                    default:
                        Util.Assert(false, "Unknown symbol in front of " + split[i]);
                        break;
                }
            }
            return boxes;
        }
    }
}
{'fraction_non_alphanumeric': 0.11158173395102582, 'fraction_numerical': 0.002911978821972204, 'mean_word_length': 1.595671590518722, 'pattern_counts': {'":': 0, '<': 37, '<?xml version=': 0, '>': 59, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6519970', 'n_tokens_mistral': 2069, 'n_tokens_neox': 1977, 'n_words': 556}