forked from NaiJi/project-kyoku
69 lines
1.8 KiB
C++
69 lines
1.8 KiB
C++
#ifndef PRECISIONEVALUATOR_H
|
|
#define PRECISIONEVALUATOR_H
|
|
|
|
#include <numeric>
|
|
#include <type_traits>
|
|
#include <vector>
|
|
#include <cmath>
|
|
#include <iostream>
|
|
|
|
#include <SFML/System/Clock.hpp>
|
|
|
|
using microsec = sf::Int64;
|
|
|
|
template<typename Grade, typename = std::enable_if_t<std::is_enum<Grade>::value>>
|
|
class PrecisionEvaluator
|
|
{
|
|
public:
|
|
PrecisionEvaluator(const std::vector<microsec>& intervals, microsec offset) :
|
|
_offset(offset),
|
|
_intervals(intervals)
|
|
{
|
|
_start_handling_offset = _offset - intervals.back();
|
|
_end_handling_offset = _offset + intervals.back();
|
|
}
|
|
|
|
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 noexcept
|
|
{
|
|
microsec shift_from_perfect = std::abs(odds - offset());
|
|
|
|
std::cout << "Shift " << ((odds > _offset) ? "late: " : "early: ") << shift_from_perfect << "\n";
|
|
|
|
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<Grade>(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<microsec>& _intervals;
|
|
};
|
|
|
|
#endif // PRECISIONEVALUATOR_H
|