<commit_before>﻿using System;
using System.Diagnostics;
using System.Globalization;
using System.Windows;
using DereTore;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;

namespace StarlightDirector.Entities {
    [JsonObject(NamingStrategyType = typeof(CamelCaseNamingStrategy), MemberSerialization = MemberSerialization.OptIn)]
    public sealed class Note : DependencyObject, IComparable<Note> {

        public event EventHandler<EventArgs> ExtraParamsChanged;

        [JsonProperty]
        public int ID { get; private set; }

        [JsonIgnore]
        public double HitTiming => Bar.TimeAtGrid(IndexInGrid);

        private int _indexInGrid;

        // "PositionInGrid" was the first name of this property used in serialization.
        [JsonProperty("positionInGrid")]
        public int IndexInGrid {
            get { return _indexInGrid; }
            set {
                _indexInGrid = value;
                Bar?.SortNotes();
            }
        }

        public NoteType Type {
            get { return (NoteType)GetValue(TypeProperty); }
            internal set { SetValue(TypeProperty, value); }
        }

        [JsonProperty]
        public NotePosition StartPosition {
            get { return (NotePosition)GetValue(StartPositionProperty); }
            set { SetValue(StartPositionProperty, value); }
        }

        [JsonProperty]
        public NotePosition FinishPosition {
            get { return (NotePosition)GetValue(FinishPositionProperty); }
            set { SetValue(FinishPositionProperty, value); }
        }

        public int IndexInTrack => (int)FinishPosition - 1;

        [JsonProperty]
        public NoteFlickType FlickType {
            get { return (NoteFlickType)GetValue(FlickTypeProperty); }
            set { SetValue(FlickTypeProperty, value); }
        }

        public bool IsSync {
            get { return (bool)GetValue(IsSyncProperty); }
            private set { SetValue(IsSyncProperty, value); }
        }

        public Bar Bar { get; internal set; }

        public bool IsFlick {
            get { return (bool)GetValue(IsFlickProperty); }
            private set { SetValue(IsFlickProperty, value); }
        }

        [JsonProperty("prevFlickNoteID")]
        public int PrevFlickOrSlideNoteID { get; internal set; }

        public Note PrevFlickOrSlideNote {
            get { return _prevFlickOrSlideNote; }
            set {
                UpdateFlickTypeStep1(value);
                _prevFlickOrSlideNote = value;
                UpdateFlickTypeStep2();
                PrevFlickOrSlideNoteID = value?.ID ?? EntityID.Invalid;
            }
        }

        public bool HasPrevFlickOrSlide => (Type == NoteType.TapOrFlick || Type == NoteType.Slide) && PrevFlickOrSlideNote != null;

        [JsonProperty("nextFlickNoteID")]
        public int NextFlickOrSlideNoteID { get; internal set; }

        public Note NextFlickOrSlideNote {
            get { return _nextFlickOrSlideNote; }
            set {
                UpdateFlickTypeStep1(value);
                _nextFlickOrSlideNote = value;
                UpdateFlickTypeStep2();
                NextFlickOrSlideNoteID = value?.ID ?? EntityID.Invalid;
            }
        }

        public bool HasNextFlickOrSlide => (Type == NoteType.TapOrFlick || Type == NoteType.Slide) && NextFlickOrSlideNote != null;

        [Obsolete("This property is provided for forward compatibility only.")]
        [JsonProperty]
        public int SyncTargetID {
            get {
                // For legacy versions that generate sync connection from this field
                // Connect the first note and the last note of sync groups
                if (HasPrevSync) {
                    if (HasNextSync) {
                        return EntityID.Invalid;
                    }
                    var final = PrevSyncTarget;
                    while (final.HasPrevSync) {
                        final = final.PrevSyncTarget;
                    }
                    return final.ID;
                } else {
                    if (!HasNextSync) {
                        return EntityID.Invalid;
                    }
                    var final = NextSyncTarget;
                    while (final.HasNextSync) {
                        final = final.NextSyncTarget;
                    }
                    return final.ID;
                }
            }
        }

        public Note PrevSyncTarget {
            get { return _prevSyncTarget; }
            internal set { SetPrevSyncTargetInternal(value); }
        }

        public Note NextSyncTarget {
            get { return _nextSyncTarget; }
            internal set { SetNextSyncTargetInternal(value); }
        }

        public bool HasPrevSync => PrevSyncTarget != null;

        public bool HasNextSync => NextSyncTarget != null;

        public bool IsHold {
            get { return (bool)GetValue(IsHoldProperty); }
            private set { SetValue(IsHoldProperty, value); }
        }

        public bool IsHoldStart => Type == NoteType.Hold && HoldTarget != null;

        public bool IsHoldEnd => (Type == NoteType.TapOrFlick || Type == NoteType.Slide) && HoldTarget != null;

        [JsonProperty]
        public int HoldTargetID { get; internal set; }

        public Note HoldTarget {
            get { return _holdTarget; }
            set {
                var origHoldTarget = _holdTarget;
                _holdTarget = value;<commit_msg>[director] Slide notes cannot appear at hold end.<commit_after>﻿using System;
using System.Diagnostics;
using System.Globalization;
using System.Windows;
using DereTore;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;

namespace StarlightDirector.Entities {
    [JsonObject(NamingStrategyType = typeof(CamelCaseNamingStrategy), MemberSerialization = MemberSerialization.OptIn)]
    public sealed class Note : DependencyObject, IComparable<Note> {

        public event EventHandler<EventArgs> ExtraParamsChanged;

        [JsonProperty]
        public int ID { get; private set; }

        [JsonIgnore]
        public double HitTiming => Bar.TimeAtGrid(IndexInGrid);

        private int _indexInGrid;

        // "PositionInGrid" was the first name of this property used in serialization.
        [JsonProperty("positionInGrid")]
        public int IndexInGrid {
            get { return _indexInGrid; }
            set {
                _indexInGrid = value;
                Bar?.SortNotes();
            }
        }

        public NoteType Type {
            get { return (NoteType)GetValue(TypeProperty); }
            internal set { SetValue(TypeProperty, value); }
        }

        [JsonProperty]
        public NotePosition StartPosition {
            get { return (NotePosition)GetValue(StartPositionProperty); }
            set { SetValue(StartPositionProperty, value); }
        }

        [JsonProperty]
        public NotePosition FinishPosition {
            get { return (NotePosition)GetValue(FinishPositionProperty); }
            set { SetValue(FinishPositionProperty, value); }
        }

        public int IndexInTrack => (int)FinishPosition - 1;

        [JsonProperty]
        public NoteFlickType FlickType {
            get { return (NoteFlickType)GetValue(FlickTypeProperty); }
            set { SetValue(FlickTypeProperty, value); }
        }

        public bool IsSync {
            get { return (bool)GetValue(IsSyncProperty); }
            private set { SetValue(IsSyncProperty, value); }
        }

        public Bar Bar { get; internal set; }

        public bool IsFlick {
            get { return (bool)GetValue(IsFlickProperty); }
            private set { SetValue(IsFlickProperty, value); }
        }

        [JsonProperty("prevFlickNoteID")]
        public int PrevFlickOrSlideNoteID { get; internal set; }

        public Note PrevFlickOrSlideNote {
            get { return _prevFlickOrSlideNote; }
            set {
                UpdateFlickTypeStep1(value);
                _prevFlickOrSlideNote = value;
                UpdateFlickTypeStep2();
                PrevFlickOrSlideNoteID = value?.ID ?? EntityID.Invalid;
            }
        }

        public bool HasPrevFlickOrSlide => (Type == NoteType.TapOrFlick || Type == NoteType.Slide) && PrevFlickOrSlideNote != null;

        [JsonProperty("nextFlickNoteID")]
        public int NextFlickOrSlideNoteID { get; internal set; }

        public Note NextFlickOrSlideNote {
            get { return _nextFlickOrSlideNote; }
            set {
                UpdateFlickTypeStep1(value);
                _nextFlickOrSlideNote = value;
                UpdateFlickTypeStep2();
                NextFlickOrSlideNoteID = value?.ID ?? EntityID.Invalid;
            }
        }

        public bool HasNextFlickOrSlide => (Type == NoteType.TapOrFlick || Type == NoteType.Slide) && NextFlickOrSlideNote != null;

        [Obsolete("This property is provided for forward compatibility only.")]
        [JsonProperty]
        public int SyncTargetID {
            get {
                // For legacy versions that generate sync connection from this field
                // Connect the first note and the last note of sync groups
                if (HasPrevSync) {
                    if (HasNextSync) {
                        return EntityID.Invalid;
                    }
                    var final = PrevSyncTarget;
                    while (final.HasPrevSync) {
                        final = final.PrevSyncTarget;
                    }
                    return final.ID;
                } else {
                    if (!HasNextSync) {
                        return EntityID.Invalid;
                    }
                    var final = NextSyncTarget;
                    while (final.HasNextSync) {
                        final = final.NextSyncTarget;
                    }
                    return final.ID;
                }
            }
        }

        public Note PrevSyncTarget {
            get { return _prevSyncTarget; }
            internal set { SetPrevSyncTargetInternal(value); }
        }

        public Note NextSyncTarget {
            get { return _nextSyncTarget; }
            internal set { SetNextSyncTargetInternal(value); }
        }

        public bool HasPrevSync => PrevSyncTarget != null;

        public bool HasNextSync => NextSyncTarget != null;

        public bool IsHold {
            get { return (bool)GetValue(IsHoldProperty); }
            private set { SetValue(IsHoldProperty, value); }
        }

        public bool IsHoldStart => Type == NoteType.Hold && HoldTarget != null;

        public bool IsHoldEnd => Type == NoteType.TapOrFlick && HoldTarget != null;

        [JsonProperty]
        public int HoldTargetID { get; internal set; }

        public Note HoldTarget {
            get { return _holdTarget; }
            set {
                var origHoldTarget = _holdTarget;
                _holdTarget = value;
{'fraction_non_alphanumeric': 0.07770886537759941, 'fraction_numerical': 0.0009120758847136082, 'mean_word_length': 1.7759493670886075, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 23, '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': '1537286', 'n_tokens_mistral': 2854, 'n_tokens_neox': 2704, 'n_words': 673}