/// <summary>
        /// The get subsequence characteristic.
        /// </summary>
        /// <param name="subsequenceId">
        /// The subsequence id.
        /// </param>
        /// <param name="characteristicLinkId">
        /// The characteristic type link id.
        /// </param>
        /// <param name="windowSize">
        /// The window size.
        /// </param>
        /// <param name="step">
        /// The step.
        /// </param>
        /// <returns>
        /// The <see cref="string"/>.
        /// </returns>
        public string GetSubsequenceCharacteristic(
            long subsequenceId,
            short characteristicLinkId,
            int windowSize,
            int step)
        {
            Chain           chain;
            IFullCalculator calculator;
            Link            link;

            using (var db = new LibiadaWebEntities())
            {
                var characteristicTypeLinkRepository = FullCharacteristicRepository.Instance;

                FullCharacteristic characteristic =
                    characteristicTypeLinkRepository.GetCharacteristic(characteristicLinkId);
                calculator = FullCalculatorsFactory.CreateCalculator(characteristic);
                link       = characteristicTypeLinkRepository.GetLinkForCharacteristic(characteristicLinkId);

                var subsequenceExtractor = new SubsequenceExtractor(db);

                Subsequence subsequence = db.Subsequence.Single(s => s.Id == subsequenceId);
                chain = subsequenceExtractor.GetSubsequenceSequence(subsequence);
            }

            CutRule cutRule = new SimpleCutRule(chain.Length, step, windowSize);

            CutRuleIterator iterator = cutRule.GetIterator();

            var fragments = new List <Chain>();

            while (iterator.Next())
            {
                int start = iterator.GetStartPosition();
                int end   = iterator.GetEndPosition();

                var fragment = new List <IBaseObject>();
                for (int k = 0; start + k < end; k++)
                {
                    fragment.Add(chain[start + k]);
                }

                fragments.Add(new Chain(fragment));
            }

            var characteristics = new double[fragments.Count];

            for (int k = 0; k < fragments.Count; k++)
            {
                characteristics[k] = calculator.Calculate(fragments[k], link);
            }

            return(JsonConvert.SerializeObject(characteristics));
        }
        public ActionResult Index(
            long[] matterIds,
            short[] characteristicLinkIds,
            int length,
            int step,
            bool delta,
            bool fourier,
            bool growingWindow,
            bool autocorrelation,
            Notation notation,
            Language?language,
            Translator?translator,
            PauseTreatment?pauseTreatment,
            bool?sequentialTransfer,
            ImageOrderExtractor?trajectory)
        {
            return(CreateTask(() =>
            {
                var characteristicNames = new string[characteristicLinkIds.Length];
                var partNames = new List <string> [matterIds.Length];
                var starts = new List <int> [matterIds.Length];
                var lengthes = new List <int> [matterIds.Length];
                var chains = new Chain[matterIds.Length];
                var mattersCharacteristics = new object[matterIds.Length];

                var calculators = new IFullCalculator[characteristicLinkIds.Length];
                var links = new Link[characteristicLinkIds.Length];
                matterIds = matterIds.OrderBy(m => m).ToArray();
                Dictionary <long, Matter> matters = Cache.GetInstance().Matters.Where(m => matterIds.Contains(m.Id)).ToDictionary(m => m.Id);

                for (int k = 0; k < matterIds.Length; k++)
                {
                    long matterId = matterIds[k];
                    Nature nature = Cache.GetInstance().Matters.Single(m => m.Id == matterId).Nature;

                    long sequenceId = commonSequenceRepository.GetSequenceIds(new[] { matterId },
                                                                              notation,
                                                                              language,
                                                                              translator,
                                                                              pauseTreatment,
                                                                              sequentialTransfer,
                                                                              trajectory).Single();

                    chains[k] = commonSequenceRepository.GetLibiadaChain(sequenceId);
                }

                for (var i = 0; i < characteristicLinkIds.Length; i++)
                {
                    int characteristicLinkId = characteristicLinkIds[i];
                    FullCharacteristic characteristic = characteristicTypeLinkRepository.GetCharacteristic(characteristicLinkId);
                    calculators[i] = FullCalculatorsFactory.CreateCalculator(characteristic);
                    links[i] = characteristicTypeLinkRepository.GetLinkForCharacteristic(characteristicLinkId);
                }

                for (int i = 0; i < chains.Length; i++)
                {
                    CutRule cutRule = growingWindow
                            ? (CutRule) new CutRuleWithFixedStart(chains[i].Length, step)
                            : new SimpleCutRule(chains[i].Length, step, length);

                    CutRuleIterator iterator = cutRule.GetIterator();

                    var fragments = new List <Chain>();
                    partNames[i] = new List <string>();
                    starts[i] = new List <int>();
                    lengthes[i] = new List <int>();

                    while (iterator.Next())
                    {
                        int start = iterator.GetStartPosition();
                        int end = iterator.GetEndPosition();

                        var fragment = new List <IBaseObject>();
                        for (int k = 0; start + k < end; k++)
                        {
                            fragment.Add(chains[i][start + k]);
                        }

                        fragments.Add(new Chain(fragment));

                        partNames[i].Add(fragment.ToString());
                        starts[i].Add(iterator.GetStartPosition());
                        lengthes[i].Add(fragment.Count);
                    }

                    var fragmentsData = new FragmentData[fragments.Count];
                    for (int k = 0; k < fragments.Count; k++)
                    {
                        var characteristics = new double[calculators.Length];
                        for (int j = 0; j < calculators.Length; j++)
                        {
                            characteristics[j] = calculators[j].Calculate(fragments[k], links[j]);
                        }

                        fragmentsData[k] = new FragmentData(characteristics, fragments[k].ToString(), starts[i][k], fragments[k].Length);
                    }

                    double[][] differenceData = null;
                    double[][] fourierData = null;
                    double[][] autocorrelationData = null;

                    if (delta)
                    {
                        differenceData = CalculateDifference(fragmentsData.Select(f => f.Characteristics).ToArray());
                    }

                    if (fourier)
                    {
                        fourierData = FastFourierTransform.CalculateFastFourierTransform(fragmentsData.Select(f => f.Characteristics).ToArray());
                    }

                    if (autocorrelation)
                    {
                        autocorrelationData = AutoCorrelation.CalculateAutocorrelation(fragmentsData.Select(f => f.Characteristics).ToArray());
                    }

                    mattersCharacteristics[i] = new LocalCharacteristicsData(matters[matterIds[i]].Name,
                                                                             fragmentsData,
                                                                             differenceData,
                                                                             fourierData,
                                                                             autocorrelationData);
                }

                for (int l = 0; l < characteristicLinkIds.Length; l++)
                {
                    characteristicNames[l] = characteristicTypeLinkRepository.GetCharacteristicName(characteristicLinkIds[l]);
                }

                var characteristicsList = new SelectListItem[characteristicLinkIds.Length];
                for (int k = 0; k < characteristicLinkIds.Length; k++)
                {
                    characteristicNames[k] = characteristicTypeLinkRepository.GetCharacteristicName(characteristicLinkIds[k], notation);
                    characteristicsList[k] = new SelectListItem
                    {
                        Value = k.ToString(),
                        Text = characteristicNames[k],
                        Selected = false
                    };
                }

                var result = new Dictionary <string, object>
                {
                    { "characteristics", mattersCharacteristics },
                    { "notationName", notation.GetDisplayValue() },
                    { "starts", starts },
                    { "partNames", partNames },
                    { "lengthes", lengthes },
                    { "characteristicNames", characteristicNames },
                    { "matterIds", matterIds },
                    { "characteristicsList", characteristicsList },
                    { "aligners", EnumHelper.GetSelectList(typeof(Aligner)) },
                    { "distanceCalculators", EnumHelper.GetSelectList(typeof(DistanceCalculator)) },
                    { "aggregators", EnumHelper.GetSelectList(typeof(Aggregator)) }
                };

                return new Dictionary <string, string> {
                    { "data", JsonConvert.SerializeObject(result) }
                };
            }));
        }
        public ActionResult Index(
            long matterId,
            short characteristicLinkId,
            Notation notation,
            int step,
            int initialLength,
            double accuracy)
        {
            return(CreateTask(() =>
            {
                string characteristicName;
                string mattersName;
                double[] characteristics;
                Chain sequence;
                IFullCalculator calculator;
                Link link;

                using (var db = new LibiadaWebEntities())
                {
                    var commonSequenceRepository = new CommonSequenceRepository(db);
                    mattersName = db.Matter.Single(m => matterId == m.Id).Name;
                    var sequenceId = db.CommonSequence.Single(c => matterId == c.MatterId && c.Notation == notation).Id;
                    sequence = commonSequenceRepository.GetLibiadaChain(sequenceId);

                    var characteristicTypeLinkRepository = FullCharacteristicRepository.Instance;
                    characteristicName = characteristicTypeLinkRepository.GetCharacteristicName(characteristicLinkId, notation);

                    FullCharacteristic characteristic = characteristicTypeLinkRepository.GetCharacteristic(characteristicLinkId);
                    calculator = FullCalculatorsFactory.CreateCalculator(characteristic);
                    link = characteristicTypeLinkRepository.GetLinkForCharacteristic(characteristicLinkId);
                }

                // characteristics = SequencesCharacteristicsCalculator.Calculate( new[] { sequenceId }, characteristicLinkId);

                CutRule cutRule = new CutRuleWithFixedStart(sequence.Length, step);

                Depth depthCaulc = new Depth();

                CutRuleIterator iter = cutRule.GetIterator();

                var fragments = new List <Chain>();
                var partNames = new List <string>();
                var lengthes = new List <int>();
                var teoreticalDepht = new List <double>();

                while (iter.Next())
                {
                    var fragment = new Chain(iter.GetEndPosition() - iter.GetStartPosition());

                    for (int k = 0; iter.GetStartPosition() + k < iter.GetEndPosition(); k++)
                    {
                        fragment.Set(sequence[iter.GetStartPosition() + k], k);
                    }

                    fragments.Add(fragment);
                    partNames.Add(fragment.ToString());
                    lengthes.Add(fragment.Length);

                    teoreticalDepht.Add(depthCaulc.Calculate(fragment, Link.Start));
                }

                characteristics = new double[fragments.Count];
                for (int k = 0; k < fragments.Count; k++)
                {
                    characteristics[k] = calculator.Calculate(fragments[k], link);
                    // fragmentsData[k] = new FragmentData(characteristics, fragments[k].ToString(), starts[i][k], fragments[k].Length);
                }



                // var predicted = new List<Chain>();

                //int[] startingPart = new int[initialLength];


                Chain predicted = new Chain(initialLength);

                for (int i = 0; i < initialLength; i++)
                {
                    predicted.Set(sequence[i], i);
                }

                Alphabet alphabet = sequence.Alphabet;
                IEnumerator enumerator = alphabet.GetEnumerator();
                var sequencePredictionResult = new List <SequencePredictionData>();

                for (int i = initialLength; i < sequence.Length; i++)
                {
                    Chain temp = new Chain(i + 1);
                    for (int j = 0; j < i; j++)
                    {
                        temp.Set(predicted[j], j);
                    }
                    predicted = temp;
                    double depth = 0;

                    /* do
                     * {
                     *   predicted.Set((IBaseObject)enumerator.Current, i);
                     *   depth = depthCaulc.Calculate(predicted, Link.Start);
                     *   if (System.Math.Abs(depth - teoreticalDepht.ElementAt(i)) <= accuracy)
                     *   {
                     *       break;
                     *   }
                     * } while (enumerator.MoveNext());*/
                    IBaseObject predictedLetter = null;
                    foreach (IBaseObject letter in alphabet)
                    {
                        predicted.Set(letter, i);
                        depth = depthCaulc.Calculate(predicted, Link.Start);
                        if (System.Math.Abs(depth - teoreticalDepht.ElementAt(i)) <= accuracy)
                        {
                            predictedLetter = letter;
                            break;
                        }
                    }



                    sequencePredictionResult.Add(new SequencePredictionData
                    {
                        Fragment = fragments.ElementAt(i).ToString(),
                        Predicted = /*enumerator.Current.ToString()*/ predicted.ToString(),
                        ActualCharacteristic = depth,
                        TheoreticalCharacteristic = teoreticalDepht.ElementAt(i)
                    });
                }

                /*int equal = 0;
                 * for (int i = initialLength; i < sequence.Length; i++)
                 * {
                 *  if (sequence[i] == predicted[i])
                 *  {
                 *      equal++;
                 *  }
                 * }
                 *
                 *
                 * double accuracyPercentage = equal / (sequence.Length - initialLength);*/


                // TODO: sequence prediction


                var result = new Dictionary <string, object>
                {
                    { "result", sequencePredictionResult }
                };

                return new Dictionary <string, object>
                {
                    { "data", JsonConvert.SerializeObject(result) }
                };
            }));
        }