3 This file is part of R²C²
4 Copyright © 2011 Mikkosoft Productions, Mikko Rasa
5 Distributed under the GPL
8 #include "speedquantizer.h"
15 SpeedQuantizer::SpeedQuantizer(unsigned n):
20 throw InvalidParameterValue("Must have at leats one speed step");
23 void SpeedQuantizer::learn(unsigned i, float s, float w)
26 throw InvalidParameterValue("Speed step index out of range");
30 float SpeedQuantizer::get_speed(unsigned i) const
34 if(steps[i].weight>=weight_limit)
35 return steps[i].speed;
39 for(low=i; low>0; --low)
40 if(steps[low].weight>=weight_limit)
42 for(high=i; high+1<steps.size(); ++high)
43 if(steps[high].weight>=weight_limit)
46 if(steps[high].weight)
49 return (steps[low].speed*(high-i)+steps[high].speed*(i-low))/(high-low);
51 return steps[high].speed*i/high;
53 else if(steps[low].weight)
54 return steps[low].speed*i/low;
59 float SpeedQuantizer::quantize_speed(float speed) const
61 return get_speed(find_speed_step(speed));
64 unsigned SpeedQuantizer::find_speed_step(float speed) const
66 if(speed<=steps[1].speed*0.5)
72 for(unsigned i=0; (!high && i<steps.size()); ++i)
73 if(steps[i].weight>=weight_limit)
76 if(steps[i].speed>=speed)
78 else if(steps[i].speed>steps[low].speed)
84 unsigned limit = steps.size()/5;
92 return min(min(static_cast<unsigned>(low*speed/steps[low].speed), steps.size()-1), last+limit);
95 float f = (speed-steps[low].speed)/(steps[high].speed-steps[low].speed);
96 return static_cast<unsigned>(low*(1-f)+high*f+0.5);
99 void SpeedQuantizer::save(list<DataFile::Statement> &st) const
101 for(unsigned i=0; i<steps.size(); ++i)
103 st.push_back((DataFile::Statement("step"), i, steps[i].speed, steps[i].weight));
107 SpeedQuantizer::SpeedStep::SpeedStep():
112 void SpeedQuantizer::SpeedStep::add(float s, float w)
114 speed = (speed*weight+s*w)/(weight+w);
115 weight = min(weight+w, 300.0f);
119 SpeedQuantizer::Loader::Loader(SpeedQuantizer &q):
120 DataFile::ObjectLoader<SpeedQuantizer>(q)
122 add("step", &Loader::step);
125 void SpeedQuantizer::Loader::step(unsigned i, float s, float w)
127 if(i>=obj.steps.size())
130 obj.steps[i].speed = s;
131 obj.steps[i].weight = w;