#ifndef PRECISIONEVALUATOR_H #define PRECISIONEVALUATOR_H #include #include #include #include #include using microsec = sf::Int64; template::value>> class PrecisionEvaluator { public: PrecisionEvaluator(const std::vector& intervals, microsec offset) : _offset(offset), _intervals(intervals) { microsec&& handling_offset = std::accumulate(intervals.begin(), intervals.end(), 0); _start_handling_offset = _offset - handling_offset; _end_handling_offset = _offset + handling_offset; } inline microsec offset() const noexcept { return _offset; } inline bool isActive(microsec music_play_offset) const noexcept { return music_play_offset > _start_handling_offset && music_play_offset < _end_handling_offset; } inline GRADE calculatePrecision(microsec odds) const { microsec shift_from_perfect = std::abs(odds - offset()); std::size_t raw_grade; for (raw_grade = 0; raw_grade < _intervals.size(); ++raw_grade) { if (shift_from_perfect <= _intervals.at(raw_grade)) break; } return static_cast(raw_grade); } private: microsec _offset; microsec _start_handling_offset; microsec _end_handling_offset; /* Amount of values in enum instanced as GRADES * represents capacity of _intervals. * So, for each V value in GRADES enum, _intervals[V] * should return time shift from V - 1. * V0 is PERFECT SCORE and the last V represents the worst * grades which is death of note by expiration */ const std::vector& _intervals; }; #endif // PRECISIONEVALUATOR_H