Skip to content

Instantly share code, notes, and snippets.

@Artoria2e5
Last active September 22, 2016 18:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Artoria2e5/624221a73d74b9be55326bf64fc4dc76 to your computer and use it in GitHub Desktop.
Save Artoria2e5/624221a73d74b9be55326bf64fc4dc76 to your computer and use it in GitHub Desktop.
KIPR Remote Control Shell
// kiprsh -- the Kipr Idiot's Private Remote Shell (the Heck?)
// Copyright (C) Mikumo Kagurazaka "Artoria2e5" <arthur2e5@aosc.xyz>
//
// compile with:
// g++ -std=gnu++11 -lwallaby -lm -ljpeg -lpthread -lopencv_core -lopencv_imgproc -lrt -lz
//
// Dual-Licensed under the MIT/Expat License and the DBAD License. ABSOLUTELY NO WARRANTY.
//
// Port to https://github.com/Svalorzen/cpp-readline for command history, or use Python...
//
// Hey where is the SWIG Python binding for libwallaby?
// I'd rather use plain Python to debug & test the [...] "go-and-msleep-and-stop" sequence.
// Even writing bash builtins is much better than hand-tokenizing like this.
#include <iostream>
#include <string>
#include <vector>
#include <unordered_map>
#include <sstream>
#include <algorithm>
#include <iterator>
#include <functional>
#include <cstdio>
#include <cstdlib>
#ifdef SYNTAX_CHK
// fake funcs
static void create_drive_direct(int left, int right) {return;}
static int create_connect(void) {return 0;}
static void msleep(long) {return 3;}
static int mav(int m, int v) {return 3;}
#else
#include <kipr/botball.h>
#endif
using namespace std;
// You see, we don't need C++14 for this...
string operator "" _s(const char *str, std::size_t len);
string operator "" _s(const char *str, std::size_t len) {
return std::string{str, len};
}
int move(int left, int right, int time);
struct Call {
int arity;
function <int(vector<string>)> eval;
};
int main(int argc, char **argv, char **envp) {
// A bunch of available functions / commands.
// Try to add some other funcs yourself.
unordered_map<string, Call> avail_funcs = {
{"cmov", {3, [](vector<string> v){ return move(stoi(v[1]),stoi(v[2]),stoi(v[3])); }}},
{"quit", {0, [](vector<string> v){ exit(2); return 42; }}},
{"exit", {1, [](vector<string> v){ exit(stoi(v[1])); return 42; }}},
{"mavt", {3, [](vector<string> v){
int i = mav(stoi(v[1]), stoi(v[2]));
if (stoi(v[3]) > 0) {
msleep(stoi(v[3]));
i |= (mav(stoi(v[1]), 0) << 8);
}
return i;
}}},
{"wait", {1, [](vector<string> v){ msleep(stoi(v[0])); return 0; }}},
{"conn", {0, [](vector<string> v){ return create_connect(); }}},
{"help", {0, [&avail_funcs](vector<string> v){
cout << "kiprsh 0.2, compiled " << __DATE__ << " " << __TIME__ << endl;
for (const auto& n : avail_funcs)
cout << n.first << ", ";
cout << "and that's all the commands I know." << endl;
return 0;
}}},
};
// aliases
avail_funcs["C"] = avail_funcs["cmov"];
avail_funcs["M"] = avail_funcs["mavt"];
string cmd;
while (getline(cin, cmd)) {
stringstream ss(cmd);
vector<string> tokens{istream_iterator<string>(ss),
istream_iterator<string>()};
#ifdef DUMP_PARSE
cout << "parse: ";
for (auto tok : tokens) {
cout << '\'' << tok << "\', ";
}
cout << " end." << endl;
#endif
if (tokens.size() < 1)
{
cout << endl;
continue;
}
int ret = 666;
try {
Call func = avail_funcs.at(tokens[0]);
if (func.arity == tokens.size() - 1)
{
ret = func.eval(tokens);
} else {
string ouch = "arity: want "_s + to_string(func.arity) + ", got "_s + to_string(tokens.size() - 1);
auto ah = invalid_argument(ouch);
throw ah;
}
} catch (const std::out_of_range& e) {
cerr << "command not found: " << tokens[0] << endl;
} catch (const std::exception& e) {
cerr << e.what() << endl;
}
cout << "=> " << ret << endl;
}
return 0;
}
int move(int left, int right, int time) {
create_drive_direct(left,right);
msleep(time);
create_drive_direct(0,0);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment