Skip to content

Instantly share code, notes, and snippets.

@plasma-effect
Last active September 27, 2016 17:42
Show Gist options
  • Save plasma-effect/9bb43b20ab1412d2f557009b0076f721 to your computer and use it in GitHub Desktop.
Save plasma-effect/9bb43b20ab1412d2f557009b0076f721 to your computer and use it in GitHub Desktop.

Siv3Dregexpr.hppboostがないと動きません

セットアップ方法

自分でビルドしたい!

  • Siv3DをVS2015にインストールします
  • Siv3Dプロジェクトを新規作成します
  • regexpr.hppというファイルを追加して上のregexpr.hppをコピペします
  • Main.cppに下のMain.cppをコピペします
  • Debugって書いてあるとこをReleaseにしてx86って書いてあるとこをx64にします
  • Ctrl+Shift+Bでビルドします
  • 実行ファイルができるはずですがそれがタイマーです

実行ファイルが欲しい!

ネットで転がってる実行ファイルの中確認せず使うの…?マジで…?こちら

使い方

とにかく使いたい!

Enter押したらタイマーが起動してEnter押す度に記録してくれる
途中飛ばしたくなったらSpaceを押すと飛ばしてくれる
最後までいった場合に関しては下

ターゲットデータを使いたい!

タイマーが動いていない時にCを押すと現在登録されている記録一覧が出るのでターゲットにしたい記録をチェックする
Enterボタン(キーボードのEnterではない!)を押すとタイマーの準備ができる
Shiftを押すとターゲットを切り替えることができる ターゲットデータを追加したい場合は下みたいな内容のテキストファイルを作ってDを押すと読み込める(ただし何時間単位から書かないと読み込まないので注意)

00:00:10.000
00:00:20.000
00:00:30.000
00:00:40.000
00:00:50.000

セグメントデータを読み込みたい!

Lを押すとなんか出てくるのでラジオボタンをsegmentに合わせてファイル名を入力してEnterボタン(キーボードのではない)を押す
セグメントデータは以下の形式で書かないといけない

1st segment
2nd segment
3rd segment
4th segment

あと4つぐらいセグメントないとエラー吐いて落ちる

自分の記録を保存したい!

Sを押すとなんか出てくるのでファイル名書いてEnterボタンを押す
読み込む場合はLを押してdataに合わせてファイル名書いてEnterボタン

自分の記録を出力したい!

Pを押すとmy_recodes.txtに吐き出されるので活用しましょう

カンペしたい!

まずカンペに使う画像ファイルを複数枚用意する(480x360のpngが望ましい)
そのファイルのパスをテキストファイルに縦に並べる

0.png
1.png
2.png

Lを押してgalleryに合わせてファイル名書いてEnterボタン

お問い合わせ

@plasma_parseか@plasma_eまで。お前が見えてなくても俺は見えている。フォローするかもしれないししないかもしれない。

#include<Siv3D.hpp>
#include<chrono>
#include<vector>
#include<functional>
#include"regexpr.hpp"
namespace sch = std::chrono;
typedef sch::milliseconds base_time_t;
class data_t
{
std::vector<s3d::String> segment_name;
std::map<s3d::String, std::vector<s3d::Optional<std::pair<int, base_time_t>>>> recodes;
std::map<s3d::String, std::vector<s3d::Optional<base_time_t>>> targets;
public:
data_t(std::vector<s3d::String>segment) :
segment_name(std::move(segment)), recodes(), targets()
{
}
template<class Archive>void serialize(Archive& archive)
{
archive(segment_name);
archive(recodes);
archive(targets);
}
bool add_recode(s3d::String name, std::vector<s3d::Optional<std::pair<int, base_time_t>>>&& times)
{
if (recodes.count(name))
{
return false;
}
recodes.emplace(name, std::move(times));
return true;
}
bool add_target(s3d::String name, std::vector<s3d::Optional<base_time_t>>&& data)
{
if (targets.count(name))
{
return false;
}
targets.emplace(name, std::move(data));
return true;
}
auto sum_of_best_segment()const
{
std::vector<s3d::Optional<base_time_t>> ret(segment_name.size());
for (auto& p : recodes)
{
auto& vec = p.second;
if (!vec.front())
continue;
if (!ret.front())
{
ret.front() = vec.front()->second;
}
else if (*ret.front() > vec.front()->second)
{
ret.front() = vec.front()->second;
}
}
for (std::size_t i = 1;i < segment_name.size();++i)
{
for (auto& p : recodes)
{
auto& vec = p.second;
if (!vec[i])
continue;
if (!ret[i])
{
auto index = i - vec[i]->first;
if (index < 0)
{
ret[i] = vec[i]->second;
}
else if (ret[index])
{
ret[i] = vec[i]->second - vec[index]->second + *ret[index];
}
}
else
{
auto index = i - vec[i]->first;
if (index < 0)
{
ret[i] = std::min(*ret[i], vec[i]->second);
}
else if (ret[index])
{
ret[i] = std::min(*ret[i], vec[i]->second - vec[index]->second + *ret[index]);
}
}
}
}
return ret;
}
auto best_recode()const
{
std::vector<s3d::Optional<base_time_t>> ret(segment_name.size());
if (recodes.size())
{
s3d::Optional<std::reference_wrapper<s3d::String const>> target;
base_time_t time{};
for (auto const& p : recodes)
{
auto const& vec = p.second;
if (!vec.back())
continue;
if (!target)
{
target.emplace(p.first);
time = vec.back()->second;
}
else
{
if (vec.back()->second < time)
{
target.emplace(p.first);
time = vec.back()->second;
}
}
}
if (target)
{
auto const& vec = recodes.at(*target);
for (std::size_t i{};i < segment_name.size();++i)
{
if (vec[i])
{
ret[i] = vec[i]->second;
}
}
}
}
return ret;
}
std::vector<s3d::String> const& segment()const
{
return segment_name;
}
std::vector<s3d::Optional<base_time_t>>operator[](s3d::String const& name)const
{
std::vector<s3d::Optional<base_time_t>> ret;
if (recodes.count(name))
{
auto const& vec = recodes.at(name);
for (auto const& p : vec)
{
ret.emplace_back(p ? s3d::make_Optional(p->second) : s3d::none);
}
}
else if (targets.count(name))
{
ret = targets.at(name);
}
else
{
ret.resize(segment_name.size());
}
return ret;
}
std::pair<std::vector<s3d::String>,std::vector<s3d::String>> get_recodes_name()const
{
std::pair<std::vector<s3d::String>, std::vector<s3d::String>> ret;
for (auto const& p : recodes)
{
ret.first.emplace_back(p.first);
}
for (auto const& p : targets)
{
ret.second.emplace_back(p.first);
}
return ret;
}
};
s3d::String time_to_string(base_time_t time)
{
auto count = time.count();
auto hour = count / (60 * 60 * 1000);
auto min = (count / (60 * 1000)) % 60;
auto sec = (count / 1000) % 60;
auto msec = count % 1000;
return s3d::Format(
hour < 10 ? L"0" : L"", hour, L":",
min < 10 ? L"0" : L"", min, L":",
sec < 10 ? L"0" : L"", sec, L".",
msec < 100 ? L"0" : L"", msec < 10 ? L"0" : L"", msec);
}
s3d::String time_to_string(s3d::Optional<base_time_t> time)
{
if (time)
return time_to_string(*time);
return L"xx:xx:xx.xxx";
}
s3d::String time_to_string(s3d::Optional<std::pair<int, base_time_t>> time)
{
if (time)
return time_to_string(time->second);
return L"xx:xx:xx.xxx";
}
std::pair<s3d::String, s3d::Color> diff_string(s3d::Optional<base_time_t> lhs, s3d::Optional<base_time_t> rhs)
{
if (lhs&&rhs)
{
auto time = *lhs - *rhs;
if (time < base_time_t())
{
return std::make_pair(L"-" + time_to_string(-time), s3d::Palette::Green);
}
else if (time > base_time_t())
{
return std::make_pair(L"+" + time_to_string(time), s3d::Palette::Red);
}
return std::make_pair(s3d::String(L"+00:00:00.000"), s3d::Palette::White);
}
return std::make_pair(s3d::String(L"+XX:XX:XX.XXX"), s3d::Palette::White);
}
std::vector<s3d::String> import_segment_data(s3d::String const& filename)
{
s3d::TextReader reader(filename);
s3d::String str;
std::vector<s3d::String> ret;
while (reader.readLine(str))
{
ret.emplace_back(str);
}
return ret;
}
class timer
{
s3d::Font main_timer_font;
s3d::Font my_recode_font;
s3d::Font target_recode_font;
s3d::Font segment_name_font;
s3d::Font diff_font;
s3d::Point point;
s3d::Size size;
s3d::Color color;
int inner_thickness;
int outer_thickness;
s3d::Point segment_name_pos;
s3d::Point my_recode_pos;
s3d::Point target_recode_pos;
s3d::Point diff_pos;
int interval_size;
std::size_t print_number;
s3d::Point main_timer_pos;
std::vector<s3d::String> segment_name;
int this_segment;
std::vector<std::vector<s3d::Optional<base_time_t>>> target;
int target_index;
std::vector<s3d::Optional<std::pair<int, base_time_t>>> my_recode;
int skip;
sch::system_clock::time_point start;
sch::system_clock::time_point now;
int plus_shift;
enum class status_t
{
wait,
run,
end
}status;
public:
void draw()
{
s3d::Rect(point, size).drawFrame(inner_thickness, outer_thickness, color);
s3d::Point interval(0, interval_size);
for (int i{};i < print_number;++i)
{
int index = this_segment >= print_number ? this_segment - i : print_number - i - 1;
int shift = print_number - i - 1;
auto diff = diff_string(my_recode[index] ? s3d::make_Optional(my_recode[index]->second) : s3d::none, target[target_index][index]);
auto pshift = diff.second == s3d::Palette::Green ? 0 : plus_shift;
segment_name_font(segment_name[index]).draw(segment_name_pos + interval*shift);
my_recode_font(time_to_string(my_recode[index])).draw(my_recode_pos + interval*shift);
target_recode_font(time_to_string(target[target_index][index])).draw(target_recode_pos + interval*shift, s3d::Palette::Yellow);
diff_font(diff.first).draw(diff_pos + interval*shift - s3d::Point(pshift, 0), diff.second);
}
auto s = sch::duration_cast<sch::milliseconds>(now - start);
s3d::Color c = s3d::Palette::White;
if (target[target_index][this_segment])
{
using namespace std::chrono_literals;
auto d = s - *target[target_index][this_segment];
if (status == status_t::wait)
{
c = s3d::Palette::White;
}
else if (d > base_time_t())
{
c = s3d::Palette::Red;
}
else if (status == status_t::end)
{
c = s3d::Palette::Green;
}
else if (d > -5000ms)
{
c = s3d::Palette::Orange;
}
}
main_timer_font(time_to_string(s)).draw(main_timer_pos, c);
}
s3d::Optional<std::vector<s3d::Optional<std::pair<int, base_time_t>>>> run()
{
if (s3d::Input::KeyShift.clicked)
{
target_index = (target_index + 1) % target.size();
}
switch (status)
{
case status_t::wait:
{
if (s3d::Input::KeyEnter.clicked)
{
start = sch::system_clock::now();
now = sch::system_clock::now();
status = status_t::run;
skip = 1;
}
}
break;
case status_t::run:
{
now = sch::system_clock::now();
if (s3d::Input::KeyEnter.clicked)
{
my_recode[this_segment] = std::make_pair(skip, sch::duration_cast<sch::milliseconds>(now - start));
skip = 1;
if (this_segment + 1 == segment_name.size())
{
status = status_t::end;
return my_recode;
}
++this_segment;
}
else if (s3d::Input::KeySpace.clicked)
{
++skip;
if (this_segment + 1 == segment_name.size())
{
status = status_t::end;
return my_recode;
}
++this_segment;
}
}
}
return s3d::none;
}
bool is_running()
{
return status == status_t::run;
}
timer(
s3d::Font _main_timer_font,
s3d::Font _my_recode_font,
s3d::Font _target_recode_font,
s3d::Font _segment_name_font,
s3d::Font _diff_font,
s3d::Point _point,
s3d::Size _size,
s3d::Color _color,
int _inner_thickness,
int _outer_thickness,
s3d::Point _segment_name_pos,
s3d::Point _my_recode_pos,
s3d::Point _target_recode_pos,
s3d::Point _diff_pos,
int _interval_size,
int _print_number,
s3d::Point _main_timer_pos,
std::vector<s3d::String>_segment_name,
std::vector<std::vector<s3d::Optional<base_time_t>>> _target,
int _plus_shift) :
main_timer_font(std::move(_main_timer_font)),
my_recode_font(std::move(_my_recode_font)),
target_recode_font(std::move(_target_recode_font)),
segment_name_font(std::move(_segment_name_font)),
diff_font(std::move(_diff_font)),
point(_point),
size(_size),
color(_color),
inner_thickness(_inner_thickness),
outer_thickness(_outer_thickness),
segment_name_pos(_segment_name_pos + _point),
my_recode_pos(_my_recode_pos + _point),
target_recode_pos(_target_recode_pos + _point),
diff_pos(_diff_pos + _point),
interval_size(_interval_size),
print_number(_print_number),
main_timer_pos(_main_timer_pos + _point),
segment_name(std::move(_segment_name)),
this_segment(0),
target(std::move(_target)),
target_index(0),
my_recode(),
skip(1),
start(),
now(),
status(status_t::wait),
plus_shift(_plus_shift)
{
if (print_number <= 0)
print_number = 1;
if (segment_name.size() < print_number)
{
for (int i{};i < print_number - segment_name.size();++i)
{
segment_name.emplace_back(L"");
}
}
if (target.size() == 0)
{
target.emplace_back(std::vector<s3d::Optional<base_time_t>>(segment_name.size()));
}
my_recode.resize(segment_name.size());
}
};
timer make_timer(
s3d::Point position,
s3d::Color color,
std::vector<s3d::String>segment,
std::vector<std::vector<s3d::Optional<base_time_t>>> target)
{
return timer{
s3d::Font(20),
s3d::Font(18),
s3d::Font(12),
s3d::Font(15),
s3d::Font(12),
position,
s3d::Point(220,355),
color,
2,
0,
s3d::Point(10,0),
s3d::Point(20,50),
s3d::Point(20,22),
s3d::Point(13,38),
75,
4,
s3d::Point(10,320),
segment,
target,
5
};
}
class gallery
{
bool flag;
std::vector<std::pair<s3d::Image, s3d::Texture>> images;
int index;
s3d::Point position;
s3d::Size size;
s3d::Font font;
public:
gallery(std::vector<s3d::String> passes, s3d::Point pos, s3d::Size s, s3d::Font f, bool flag_ = true) :
flag{ flag_ },
images{},
index{},
position{ pos },
size{ s },
font{ std::move(f) }
{
for (auto const& pass : passes)
{
images.emplace_back(s3d::Image(pass), s3d::Texture());
images.back().second = s3d::Texture(images.back().first);
}
}
void draw()
{
auto const& tex = images[index].second;
double x = flag ? static_cast<double>(size.x) / tex.size.x : 1.;
double y = flag ? static_cast<double>(size.y) / tex.size.y : 1.;
tex.scale(x, y).drawAt(position + (size / 2));
font(index + 1, L"/", images.size()).draw(position);
}
void run()
{
if (index > 0 && s3d::Input::KeyLeft.clicked)
{
--index;
}
if (index < images.size() - 1 && s3d::Input::KeyRight.clicked)
{
++index;
}
}
};
std::vector<s3d::String> import_gallery_data(s3d::FilePath const& path)
{
return import_segment_data(path);
}
void Main()
{
s3d::Window::Resize(800, 420);
s3d::Font font(16, s3d::Typeface::Medium, s3d::FontStyle::Outline);
font.changeOutlineStyle(s3d::TextOutlineStyle(s3d::Palette::White, s3d::Palette::Black, 1.));
s3d::Optional<s3d::GUI> gui;
s3d::Optional<s3d::GUI> input;
using namespace std::chrono_literals;
auto time = make_timer({ 22,22 }, s3d::Palette::Yellow, {
L"一強",
L"双璧",
L"御三家",
L"四天王",
L"五大老",
L"六武衆",
L"七英雄",
L"八王子"
}, {{
1000ms,
2000ms,
3000ms,
4000ms,
5000ms,
6000ms,
7000ms,
8000ms
}});
data_t data({
L"一強",
L"双璧",
L"御三家",
L"四天王",
L"五大老",
L"六武衆",
L"七英雄",
L"八王子"});
s3d::String name;
s3d::String message = L"";
s3d::Optional<gallery> gal;
s3d::Optional<s3d::GUI> target_select;
s3d::Optional<s3d::GUI> save;
while (s3d::System::Update())
{
if (gui)
{
if (gui->button(L"enter").pressed)
{
auto filename = gui->textField(L"filename").text;
if (gui->radioButton(L"filetype").checked(0))
{
data = data_t(import_segment_data(filename));
time = make_timer({ 22,22 }, s3d::Palette::Yellow, data.segment(), { std::vector<s3d::Optional<base_time_t>>(data.segment().size()) });
message = L"セグメントデータを読み込みました";
}
else if (gui->radioButton(L"filetype").checked(1))
{
s3d::Deserializer<s3d::BinaryReader> des(filename);
des(data);
time = make_timer({ 22,22 }, s3d::Palette::Yellow, data.segment(), { data.sum_of_best_segment() });
message = L"タイムデータを読み込みました";
name = filename;
}
else if (gui->radioButton(L"filetype").checked(2))
{
gal.emplace(import_gallery_data(filename), s3d::Point{ 300,20 }, s3d::Size{ 480,360 }, font);
message = L"ギャラリーを読み込みました";
}
gui.reset();
}
}
else if (input)
{
if (input->button(L"enter").pressed)
{
std::vector<s3d::Optional<base_time_t>> inp(data.segment().size());
int index{};
auto filename = input->textField(L"file").text;
auto vec = import_gallery_data(filename);
for (auto const& s : vec)
{
int hour;
int minute;
int second;
int ms;
using namespace regexpr;
if (parse(number[hour] + L":" + number[minute] + L":" + number[second] + L"." + number[ms], s))
{
inp[index].emplace(sch::hours(hour) + sch::minutes(minute) + sch::seconds(second) + sch::milliseconds(ms));
}
if (++index == data.segment().size())
break;
}
data.add_target(input->textField(L"name").text, std::move(inp));
message = L"ターゲットデータに追加しました:" + filename;
input.reset();
}
}
else if (target_select)
{
if (target_select->button(L"enter").pressed)
{
std::vector<std::vector<s3d::Optional<base_time_t>>> vec;
if (target_select->checkBox(L"mybest").checked(0))
{
vec.emplace_back(data.best_recode());
}
if (target_select->checkBox(L"mybest").checked(1))
{
vec.emplace_back(data.sum_of_best_segment());
}
auto const& recode = target_select->checkBox(L"recode").itemNames;
for (std::size_t i{};i < recode.size();++i)
{
if (target_select->checkBox(L"recode").checked(i))
{
vec.emplace_back(data[recode[i]]);
}
}
auto const& target = target_select->checkBox(L"target").itemNames;
for (std::size_t i{};i < target.size();++i)
{
if (target_select->checkBox(L"target").checked(i))
{
vec.emplace_back(data[target[i]]);
}
}
if (vec.size() == 0)
{
vec.emplace_back(std::vector<s3d::Optional<base_time_t>>(data.segment().size()));
}
time = make_timer({ 22,22 }, s3d::Palette::Yellow, data.segment(), std::move(vec));
target_select.reset();
}
}
else if (save)
{
if (save->button(L"enter").pressed)
{
s3d::Serializer<s3d::BinaryWriter> seri(save->textField(L"filename").text);
seri(data);
name = save->textField(L"filename").text;
message = L"保存しました" + name;
save.reset();
}
}
else if (!time.is_running())
{
if (s3d::Input::KeyL.clicked)
{
gui.emplace(s3d::GUIStyle::Default);
gui->addln(L"filename", s3d::GUITextField::Create(32));
gui->add(L"filetype", s3d::GUIRadioButton::Create({ L"segment",L"data", L"gallery" }, 0));
gui->addln(L"enter", s3d::GUIButton::Create(L"enter"));
}
else if (s3d::Input::KeyD.clicked)
{
input.emplace(s3d::GUIStyle::Default);
input->add(L"text1", s3d::GUIText::Create(L"dataname:"));
input->addln(L"name", s3d::GUITextField::Create(32));
input->add(L"text2", s3d::GUIText::Create(L"filename:"));
input->addln(L"file", s3d::GUITextField::Create(32));
input->addln(L"enter", s3d::GUIButton::Create(L"enter"));
}
else if (s3d::Input::KeyC.clicked)
{
target_select.emplace(s3d::GUIStyle::Default);
auto recodes = data.get_recodes_name();
target_select->addln(L"mybest", s3d::GUICheckBox::Create({ L"my best" ,L"sum of best segment" }));
target_select->addln(L"target", s3d::GUICheckBox::Create(s3d::Array<s3d::FilePath>(recodes.second)));
target_select->addln(L"recode", s3d::GUICheckBox::Create(s3d::Array<s3d::FilePath>(recodes.first)));
target_select->addln(L"enter", s3d::GUIButton::Create(L"enter"));
}
else if (s3d::Input::KeyS.clicked)
{
save.emplace(s3d::GUIStyle::Default);
save->addln(L"filename", s3d::GUITextField::Create(32));
save->textField(L"filename").setText(name);
save->add(L"enter", s3d::GUIButton::Create(L"enter"));
}
else if (s3d::Input::KeyP.clicked)
{
s3d::TextWriter writer(L"my_recodes.txt");
auto const& seg = data.segment();
writer.writeln(L"my best");
int index{};
for (auto const& v : data.best_recode())
{
writer.writeln(seg[index++] + L":" + time_to_string(v));
}
index = 0;
writer.writeln(L"");
writer.writeln(L"sum of best segment");
for (auto const& v : data.sum_of_best_segment())
{
writer.writeln(seg[index++] + L":" + time_to_string(v));
}
for (auto const& name : data.get_recodes_name().first)
{
index = 0;
writer.writeln(L"");
writer.writeln(name);
for (auto const& v : data[name])
{
writer.writeln(seg[index++] + L":" + time_to_string(v));
}
}
message = L"自分の記録をテキストファイルに出力しました";
}
time.run();
if (gal)gal->run();
}
else if (auto vec = time.run())
{
auto now = s3d::DateTime::Now();
auto str = s3d::ToString(now.year) + L"_" +
s3d::ToString(now.month) + L"_" +
s3d::ToString(now.day) + L"_" +
s3d::ToString(now.hour) + L"_" +
s3d::ToString(now.minute) + L"_" +
s3d::ToString(now.second);
data.add_recode(std::move(str), std::move(*vec));
}
time.draw();
if (gal)gal->draw();
font(message).draw(0, 380);
}
if (name.length)
{
s3d::Serializer<s3d::BinaryWriter> seri(name);
seri(data);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment