<commit_before>﻿using System;
using System.Collections.Generic;
using System.Linq;
using Monik.Common;

namespace Monik.Service
{
    // server methods (ala app insignt): total request, failed request (<> http 200), average response time
    // total exceptions

    public class MetricObject : IMetricObject
    {
        private const int IntervalEpsilon = 1000; // ms

        private readonly IMonik _monik;
        private readonly IRepository _repository;

        private Metric_ _dto;
        private Measure_[] _measures;

        public Metric_ Dto => _dto;

        private IWindowCalculator window;

        public MetricObject(IMonik monik, IRepository repository)
        {
            _monik = monik;
            _repository = repository;

            _dto = null;
            _measures = null;

            window = null;
        }

        public MeasureResponse GetCurrentMeasure()
        {
            lock (this)
            {
                var actualMeasure = GetMeasure(_dto.ActualID);

                return new MeasureResponse
                {
                    MetricId = _dto.ID,
                    Interval = _dto.ActualInterval,
                    Value = actualMeasure.Value
                };
            }
        }

        public WindowResponse GetWindow()
        {
            return new WindowResponse
            {
                MetricId = _dto.ID,
                Value = window == null ? 0 : window.GetValue()
            };
        }

        public MetricHistoryResponse GetMetricHistory(int amount, int skip)
        {
            var interval = _dto.ActualInterval.AddMinutes(-5 * skip);
            var historyMeasures =
                GetHistoryValuesEnumerable(skip)
                    .Take(amount)
                    .ToArray();

            return new MetricHistoryResponse
            {
                MetricId = _dto.ID,
                Interval = interval,
                Values = historyMeasures
            };
        }

        private IEnumerable<double> GetHistoryValuesEnumerable(int skip)
        {
            var dif = _dto.RangeTailID - _dto.RangeHeadID;
            var actualIdx = _dto.ActualID - _dto.RangeHeadID;
            var i = skip;
            while (i < int.MaxValue)
            {
                var index = (actualIdx - i++) % dif;
                if (index < 0)
                    index += dif;
                yield return _measures[index].Value;
            }
        }

        private Measure_ GetMeasure(long intervalId)
        {
            var actualIndx = intervalId - _dto.RangeHeadID;
            return _measures[actualIndx];
        }
        
        public void CreateNew(string name, int aggregation, Instance instance)
        {
            _dto = _repository.CreateMetric(name, aggregation, instance.ID);
            _measures = _repository.GetMeasures(_dto.ID);
        }
<commit_msg>Fix history range<commit_after>﻿using System;
using System.Collections.Generic;
using System.Linq;
using Monik.Common;

namespace Monik.Service
{
    // server methods (ala app insignt): total request, failed request (<> http 200), average response time
    // total exceptions

    public class MetricObject : IMetricObject
    {
        private const int IntervalEpsilon = 1000; // ms

        private readonly IMonik _monik;
        private readonly IRepository _repository;

        private Metric_ _dto;
        private Measure_[] _measures;

        public Metric_ Dto => _dto;

        private IWindowCalculator window;

        public MetricObject(IMonik monik, IRepository repository)
        {
            _monik = monik;
            _repository = repository;

            _dto = null;
            _measures = null;

            window = null;
        }

        public MeasureResponse GetCurrentMeasure()
        {
            lock (this)
            {
                var actualMeasure = GetMeasure(_dto.ActualID);

                return new MeasureResponse
                {
                    MetricId = _dto.ID,
                    Interval = _dto.ActualInterval,
                    Value = actualMeasure.Value
                };
            }
        }

        public WindowResponse GetWindow()
        {
            return new WindowResponse
            {
                MetricId = _dto.ID,
                Value = window == null ? 0 : window.GetValue()
            };
        }

        public MetricHistoryResponse GetMetricHistory(int amount, int skip)
        {
            var interval = _dto.ActualInterval.AddMinutes(-5 * skip);
            var historyMeasures =
                GetHistoryValuesEnumerable(skip)
                    .Take(amount)
                    .ToArray();

            return new MetricHistoryResponse
            {
                MetricId = _dto.ID,
                Interval = interval,
                Values = historyMeasures
            };
        }

        private IEnumerable<double> GetHistoryValuesEnumerable(int skip)
        {
            var dif = _dto.RangeTailID - _dto.RangeHeadID + 1;
            var actualIdx = _dto.ActualID - _dto.RangeHeadID;
            var i = skip;
            while (i < int.MaxValue)
            {
                var index = (actualIdx - i++) % dif;
                if (index < 0)
                    index += dif;
                yield return _measures[index].Value;
            }
        }

        private Measure_ GetMeasure(long intervalId)
        {
            var actualIndx = intervalId - _dto.RangeHeadID;
            return _measures[actualIndx];
        }
        
        public void CreateNew(string name, int aggregation, Instance instance)
        {
            _dto = _repository.CreateMetric(name, aggregation, instance.ID);
            _measures = _repository.GetMeasures(_dto.ID);
        }

{'fraction_non_alphanumeric': 0.0708132322536182, 'fraction_numerical': 0.003618194348725017, 'mean_word_length': 1.429886982000837, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 9, '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': '5204079', 'n_tokens_mistral': 1542, 'n_tokens_neox': 1420, 'n_words': 365}