Ввести v4 для режима текстового UI
This commit is contained in:
5
v4/cpp.includes
Normal file
5
v4/cpp.includes
Normal file
@@ -0,0 +1,5 @@
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "memory.h"
|
||||
#include "memory_Context.h"
|
||||
1
v4/gen-C++
Executable file
1
v4/gen-C++
Executable file
@@ -0,0 +1 @@
|
||||
c++ -o test_memory_C++ -std=c++11 -I. memory.cpp memory_Context.cpp memory_test.cpp main.cpp
|
||||
2
v4/gen-Python
Executable file
2
v4/gen-Python
Executable file
@@ -0,0 +1,2 @@
|
||||
echo "python3 main.py" > test_memory_Python
|
||||
chmod +x test_memory_Python
|
||||
10
v4/llm.py
Normal file
10
v4/llm.py
Normal file
@@ -0,0 +1,10 @@
|
||||
import copy
|
||||
|
||||
# Make deep copies of arguments to mimic behaviour of strongly typed languages.
|
||||
# https://stackoverflow.com/a/15398021
|
||||
def llm_by_value(f):
|
||||
def _f(*args, **kwargs):
|
||||
argsCopy = copy.deepcopy(args)
|
||||
kwargsCopy = copy.deepcopy(kwargs)
|
||||
return f(*argsCopy, **kwargsCopy)
|
||||
return _f
|
||||
29
v4/main.cpp
Normal file
29
v4/main.cpp
Normal file
@@ -0,0 +1,29 @@
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "memory_test.h"
|
||||
#include "memory_Context.h"
|
||||
|
||||
extern memory_Context memory_createContext();
|
||||
|
||||
int main() {
|
||||
memory_createContext();
|
||||
std::cout
|
||||
<< memory_test_generateConstPlayfield()
|
||||
<< std::endl
|
||||
<< memory_test_selectItem_1x()
|
||||
<< std::endl
|
||||
<< memory_test_selectItem_2x()
|
||||
<< std::endl
|
||||
<< memory_test_selectItem_3x()
|
||||
<< std::endl
|
||||
<< memory_test_shouldDeselectMismatchedItems()
|
||||
<< std::endl
|
||||
<< memory_test_shouldDeselectMismatchedItems_itemTwice()
|
||||
<< std::endl
|
||||
<< memory_test_shouldDetectVictory()
|
||||
<< std::endl
|
||||
<< memory_test_shouldHideMatchingItems()
|
||||
<< std::endl
|
||||
;
|
||||
}
|
||||
10
v4/main.py
Normal file
10
v4/main.py
Normal file
@@ -0,0 +1,10 @@
|
||||
from memory_test import *
|
||||
|
||||
print(memory_test_generateConstPlayfield())
|
||||
print(memory_test_selectItem_1x())
|
||||
print(memory_test_selectItem_2x())
|
||||
print(memory_test_selectItem_3x())
|
||||
print(memory_test_shouldDeselectMismatchedItems())
|
||||
print(memory_test_shouldDeselectMismatchedItems_itemTwice())
|
||||
print(memory_test_shouldDetectVictory())
|
||||
print(memory_test_shouldHideMatchingItems())
|
||||
123
v4/memory.cpp
Normal file
123
v4/memory.cpp
Normal file
@@ -0,0 +1,123 @@
|
||||
OPT_HEADER/OPT_INCLUDES: 'None'/'None'
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "memory.h"
|
||||
#include "memory_Context.h"
|
||||
|
||||
////////////////
|
||||
// Client initiated input
|
||||
////////////////
|
||||
|
||||
// Generate constant playfield
|
||||
memory_Context memory_generateConstPlayfield(
|
||||
memory_Context c
|
||||
) {
|
||||
std::map<int, int> idGroups = { };
|
||||
auto id = 0;
|
||||
for (auto gid = 0; gid < c.playfieldSize; ++gid) {
|
||||
idGroups[id] = gid;
|
||||
id += 1;
|
||||
idGroups[id] = gid;
|
||||
id += 1;
|
||||
}
|
||||
c.playfieldItems = idGroups;
|
||||
c.recentField = "playfieldItems";
|
||||
return c;
|
||||
}
|
||||
|
||||
// Select item
|
||||
memory_Context memory_selectItem(
|
||||
memory_Context c
|
||||
) {
|
||||
if (
|
||||
c.selectedItems.size() == 2
|
||||
) {
|
||||
c.selectedItems.clear();
|
||||
}
|
||||
c.selectedItems.push_back(c.selectedId);
|
||||
c.recentField = "selectedItems";
|
||||
return c;
|
||||
}
|
||||
|
||||
////////////////
|
||||
// System initiated reaction
|
||||
////////////////
|
||||
|
||||
// Deselect mismatched items
|
||||
//
|
||||
// Conditions:
|
||||
// 0. Two items has just been selected
|
||||
// 1. The same item has been selected twice
|
||||
// 2. Selected items are of different groups
|
||||
memory_Context memory_shouldDeselectMismatchedItems(
|
||||
memory_Context c
|
||||
) {
|
||||
if (!(
|
||||
c.recentField == "selectedItems" &&
|
||||
c.selectedItems.size() == 2
|
||||
)) {
|
||||
c.recentField = "none";
|
||||
return c;
|
||||
}
|
||||
if (
|
||||
c.selectedItems[0] == c.selectedItems[1]
|
||||
) {
|
||||
c.mismatchedItems.clear();
|
||||
c.mismatchedItems.push_back(c.selectedItems[0]);
|
||||
c.recentField = "mismatchedItems";
|
||||
return c;
|
||||
}
|
||||
if (
|
||||
c.playfieldItems[c.selectedItems[0]] != c.playfieldItems[c.selectedItems[1]]
|
||||
) {
|
||||
c.mismatchedItems.clear();
|
||||
c.mismatchedItems.push_back(c.selectedItems[0]);
|
||||
c.mismatchedItems.push_back(c.selectedItems[1]);
|
||||
c.recentField = "mismatchedItems";
|
||||
return c;
|
||||
}
|
||||
c.recentField = "none";
|
||||
return c;
|
||||
}
|
||||
|
||||
// Detect victory
|
||||
//
|
||||
// Conditions:
|
||||
// 1. Matching items have just been hidden and all items are hidden now
|
||||
memory_Context memory_shouldDetectVictory(
|
||||
memory_Context c
|
||||
) {
|
||||
if (
|
||||
c.recentField == "hiddenItems" &&
|
||||
c.hiddenItems.size() == c.playfieldItems.size()
|
||||
) {
|
||||
c.victory = true;
|
||||
c.recentField = "victory";
|
||||
return c;
|
||||
}
|
||||
c.recentField = "none";
|
||||
return c;
|
||||
}
|
||||
|
||||
// Hide matching selected items
|
||||
//
|
||||
// Conditions:
|
||||
// 1. Two items are selected and they are of the same group
|
||||
memory_Context memory_shouldHideMatchingItems(
|
||||
memory_Context c
|
||||
) {
|
||||
if (
|
||||
c.recentField == "selectedItems" &&
|
||||
c.selectedItems.size() == 2 &&
|
||||
c.playfieldItems[c.selectedItems[0]] == c.playfieldItems[c.selectedItems[1]]
|
||||
) {
|
||||
c.hiddenItems.push_back(c.selectedItems[0]);
|
||||
c.hiddenItems.push_back(c.selectedItems[1]);
|
||||
c.recentField = "hiddenItems";
|
||||
return c;
|
||||
}
|
||||
c.recentField = "none";
|
||||
return c;
|
||||
}
|
||||
|
||||
12
v4/memory.h
Normal file
12
v4/memory.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#include "memory_Context.h"
|
||||
|
||||
#ifndef memory_HEADER
|
||||
#define memory_HEADER
|
||||
|
||||
memory_Context memory_generateConstPlayfield(memory_Context);
|
||||
memory_Context memory_selectItem(memory_Context);
|
||||
memory_Context memory_shouldDeselectMismatchedItems(memory_Context);
|
||||
memory_Context memory_shouldDetectVictory(memory_Context);
|
||||
memory_Context memory_shouldHideMatchingItems(memory_Context);
|
||||
|
||||
#endif // memory_HEADER
|
||||
123
v4/memory.py
Normal file
123
v4/memory.py
Normal file
@@ -0,0 +1,123 @@
|
||||
from memory_Context import *
|
||||
from llm import *
|
||||
|
||||
########
|
||||
# Client initiated input
|
||||
########
|
||||
|
||||
# Generate constant playfield
|
||||
@llm_by_value
|
||||
def memory_generateConstPlayfield(
|
||||
c: memory_Context
|
||||
) -> memory_Context:
|
||||
idGroups: dict[int, int] = { }
|
||||
id = 0
|
||||
for gid in range(0, c.playfieldSize):
|
||||
idGroups[id] = gid
|
||||
id += 1
|
||||
idGroups[id] = gid
|
||||
id += 1
|
||||
#}
|
||||
c.playfieldItems = idGroups
|
||||
c.recentField = "playfieldItems"
|
||||
return c
|
||||
#}
|
||||
|
||||
# Select item
|
||||
@llm_by_value
|
||||
def memory_selectItem(
|
||||
c: memory_Context
|
||||
) -> memory_Context:
|
||||
if (
|
||||
len(c.selectedItems) == 2
|
||||
):
|
||||
c.selectedItems.clear()
|
||||
#}
|
||||
c.selectedItems.append(c.selectedId)
|
||||
c.recentField = "selectedItems"
|
||||
return c
|
||||
#}
|
||||
|
||||
########
|
||||
# System initiated reaction
|
||||
########
|
||||
|
||||
# Deselect mismatched items
|
||||
#
|
||||
# Conditions:
|
||||
# 0. Two items has just been selected
|
||||
# 1. The same item has been selected twice
|
||||
# 2. Selected items are of different groups
|
||||
@llm_by_value
|
||||
def memory_shouldDeselectMismatchedItems(
|
||||
c: memory_Context
|
||||
) -> memory_Context:
|
||||
if not (
|
||||
c.recentField == "selectedItems" and
|
||||
len(c.selectedItems) == 2
|
||||
):
|
||||
c.recentField = "none"
|
||||
return c
|
||||
#}
|
||||
if (
|
||||
c.selectedItems[0] == c.selectedItems[1]
|
||||
):
|
||||
c.mismatchedItems.clear()
|
||||
c.mismatchedItems.append(c.selectedItems[0])
|
||||
c.recentField = "mismatchedItems"
|
||||
return c
|
||||
#}
|
||||
if (
|
||||
c.playfieldItems[c.selectedItems[0]] != c.playfieldItems[c.selectedItems[1]]
|
||||
):
|
||||
c.mismatchedItems.clear()
|
||||
c.mismatchedItems.append(c.selectedItems[0])
|
||||
c.mismatchedItems.append(c.selectedItems[1])
|
||||
c.recentField = "mismatchedItems"
|
||||
return c
|
||||
#}
|
||||
c.recentField = "none"
|
||||
return c
|
||||
#}
|
||||
|
||||
# Detect victory
|
||||
#
|
||||
# Conditions:
|
||||
# 1. Matching items have just been hidden and all items are hidden now
|
||||
@llm_by_value
|
||||
def memory_shouldDetectVictory(
|
||||
c: memory_Context
|
||||
) -> memory_Context:
|
||||
if (
|
||||
c.recentField == "hiddenItems" and
|
||||
len(c.hiddenItems) == len(c.playfieldItems)
|
||||
):
|
||||
c.victory = True
|
||||
c.recentField = "victory"
|
||||
return c
|
||||
#}
|
||||
c.recentField = "none"
|
||||
return c
|
||||
#}
|
||||
|
||||
# Hide matching selected items
|
||||
#
|
||||
# Conditions:
|
||||
# 1. Two items are selected and they are of the same group
|
||||
@llm_by_value
|
||||
def memory_shouldHideMatchingItems(
|
||||
c: memory_Context
|
||||
) -> memory_Context:
|
||||
if (
|
||||
c.recentField == "selectedItems" and
|
||||
len(c.selectedItems) == 2 and
|
||||
c.playfieldItems[c.selectedItems[0]] == c.playfieldItems[c.selectedItems[1]]
|
||||
):
|
||||
c.hiddenItems.append(c.selectedItems[0])
|
||||
c.hiddenItems.append(c.selectedItems[1])
|
||||
c.recentField = "hiddenItems"
|
||||
return c
|
||||
#}
|
||||
c.recentField = "none"
|
||||
return c
|
||||
#}
|
||||
5
v4/memory_Context.cpp
Normal file
5
v4/memory_Context.cpp
Normal file
@@ -0,0 +1,5 @@
|
||||
#include "memory_Context.h"
|
||||
|
||||
memory_Context memory_createContext() {
|
||||
return memory_Context();
|
||||
}
|
||||
21
v4/memory_Context.h
Normal file
21
v4/memory_Context.h
Normal file
@@ -0,0 +1,21 @@
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#ifndef memory_Context_HEADER
|
||||
#define memory_Context_HEADER
|
||||
|
||||
struct memory_Context {
|
||||
std::vector<int> hiddenItems;
|
||||
std::vector<int> mismatchedItems;
|
||||
std::map<int, int> playfieldItems;
|
||||
int playfieldSize = 0;
|
||||
std::string recentField = "none";
|
||||
int selectedId = -1;
|
||||
std::vector<int> selectedItems;
|
||||
bool victory = false;
|
||||
};
|
||||
|
||||
memory_Context memory_createContext();
|
||||
|
||||
#endif // memory_Context_HEADER
|
||||
19
v4/memory_Context.py
Normal file
19
v4/memory_Context.py
Normal file
@@ -0,0 +1,19 @@
|
||||
class memory_Context:
|
||||
def __init__(self):
|
||||
self.hiddenItems = []
|
||||
self.mismatchedItems = []
|
||||
self.playfieldItems = {}
|
||||
self.playfieldSize = 0
|
||||
self.recentField = "none"
|
||||
self.selectedId = -1
|
||||
self.selectedItems = []
|
||||
self.victory = False
|
||||
|
||||
def __repr__(self):
|
||||
return self.__str__()
|
||||
|
||||
def __str__(self):
|
||||
return f"memory_Context(playfieldI/playfieldS/recentF/selectedId/selectedI: '{self.playfieldItems}'/'{self.playfieldSize}'/'{self.recentField}'/'{self.selectedId}'/'{self.selectedItems}')"
|
||||
|
||||
def memory_createContext():
|
||||
return memory_Context()
|
||||
212
v4/memory_test.cpp
Normal file
212
v4/memory_test.cpp
Normal file
@@ -0,0 +1,212 @@
|
||||
OPT_HEADER/OPT_INCLUDES: 'None'/'None'
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "memory.h"
|
||||
#include "memory_Context.h"
|
||||
|
||||
std::string memory_test_generateConstPlayfield(
|
||||
) {
|
||||
auto c = memory_createContext();
|
||||
c.playfieldSize = 2;
|
||||
c = memory_generateConstPlayfield(c);
|
||||
if (
|
||||
c.recentField == "playfieldItems" &&
|
||||
c.playfieldItems.size() == 4 &&
|
||||
c.playfieldItems[0] == 0 &&
|
||||
c.playfieldItems[1] == 0 &&
|
||||
c.playfieldItems[2] == 1 &&
|
||||
c.playfieldItems[3] == 1
|
||||
) {
|
||||
return "OK: memory_generateConstPlayfield";
|
||||
}
|
||||
return "ERR: memory_generateConstPlayfield";
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::string memory_test_selectItem_1x(
|
||||
) {
|
||||
auto c = memory_createContext();
|
||||
c.playfieldSize = 2;
|
||||
c = memory_generateConstPlayfield(c);
|
||||
// Select the first item.
|
||||
c.selectedId = 0;
|
||||
c = memory_selectItem(c);
|
||||
// See if it's in selectedItems now.
|
||||
if (
|
||||
c.recentField == "selectedItems" &&
|
||||
c.selectedItems.size() == 1 &&
|
||||
c.selectedItems[0] == 0
|
||||
) {
|
||||
return "OK: memory_selectItem_1x";
|
||||
}
|
||||
return "ERR: memory_selectItem_1x";
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::string memory_test_selectItem_2x(
|
||||
) {
|
||||
auto c = memory_createContext();
|
||||
c.playfieldSize = 2;
|
||||
c = memory_generateConstPlayfield(c);
|
||||
// Select the first two items.
|
||||
c.selectedId = 0;
|
||||
c = memory_selectItem(c);
|
||||
c.selectedId = 1;
|
||||
c = memory_selectItem(c);
|
||||
// See if both items are selected now.
|
||||
if (
|
||||
c.recentField == "selectedItems" &&
|
||||
c.selectedItems.size() == 2 &&
|
||||
c.selectedItems[0] == 0 &&
|
||||
c.selectedItems[1] == 1
|
||||
) {
|
||||
return "OK: memory_selectItem_2x";
|
||||
}
|
||||
return "ERR: memory_selectItem_2x";
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::string memory_test_selectItem_3x(
|
||||
) {
|
||||
auto c = memory_createContext();
|
||||
c.playfieldSize = 2;
|
||||
c = memory_generateConstPlayfield(c);
|
||||
// Select three items.
|
||||
c.selectedId = 0;
|
||||
c = memory_selectItem(c);
|
||||
c.selectedId = 1;
|
||||
c = memory_selectItem(c);
|
||||
c.selectedId = 2;
|
||||
c = memory_selectItem(c);
|
||||
// See if only one (last) item is selected now.
|
||||
if (
|
||||
c.recentField == "selectedItems" &&
|
||||
c.selectedItems.size() == 1 &&
|
||||
c.selectedItems[0] == 2
|
||||
) {
|
||||
return "OK: memory_selectItem_3x";
|
||||
}
|
||||
return "ERR: memory_selectItem_3x";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
std::string memory_test_shouldDeselectMismatchedItems(
|
||||
) {
|
||||
auto c = memory_createContext();
|
||||
c.playfieldSize = 2;
|
||||
c = memory_generateConstPlayfield(c);
|
||||
// Select two items of different groups.
|
||||
c.selectedId = 0;
|
||||
c = memory_selectItem(c);
|
||||
c.selectedId = 2;
|
||||
c = memory_selectItem(c);
|
||||
// Detect mismatching.
|
||||
c = memory_shouldDeselectMismatchedItems(c);
|
||||
// See if the two selected items do not match.
|
||||
if (
|
||||
c.recentField == "mismatchedItems" &&
|
||||
c.mismatchedItems.size() == 2 &&
|
||||
c.mismatchedItems[0] == 0 &&
|
||||
c.mismatchedItems[1] == 2
|
||||
) {
|
||||
return "OK: memory_shouldDeselectMismatchedItems";
|
||||
}
|
||||
return "ERR: memory_shouldDeselectMismatchedItems";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
std::string memory_test_shouldDeselectMismatchedItems_itemTwice(
|
||||
) {
|
||||
auto c = memory_createContext();
|
||||
c.playfieldSize = 2;
|
||||
c = memory_generateConstPlayfield(c);
|
||||
// Select the same item twice.
|
||||
c.selectedId = 0;
|
||||
c = memory_selectItem(c);
|
||||
c.selectedId = 0;
|
||||
c = memory_selectItem(c);
|
||||
// Detect mismatching.
|
||||
c = memory_shouldDeselectMismatchedItems(c);
|
||||
// See if the two selected items do not match.
|
||||
if (
|
||||
c.recentField == "mismatchedItems" &&
|
||||
c.mismatchedItems.size() == 1 &&
|
||||
c.mismatchedItems[0] == 0
|
||||
) {
|
||||
return "OK: memory_shouldDeselectMismatchedItems_itemTwice";
|
||||
}
|
||||
return "ERR: memory_shouldDeselectMismatchedItems_itemTwice";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
std::string memory_test_shouldDetectVictory(
|
||||
) {
|
||||
auto c = memory_createContext();
|
||||
c.playfieldSize = 2;
|
||||
c = memory_generateConstPlayfield(c);
|
||||
// Select the first two items of the same group.
|
||||
c.selectedId = 0;
|
||||
c = memory_selectItem(c);
|
||||
c.selectedId = 1;
|
||||
c = memory_selectItem(c);
|
||||
// Hide the first pair.
|
||||
c = memory_shouldHideMatchingItems(c);
|
||||
// Select the last two items of the same group.
|
||||
c.selectedId = 2;
|
||||
c = memory_selectItem(c);
|
||||
c.selectedId = 3;
|
||||
c = memory_selectItem(c);
|
||||
// Hide the second pair.
|
||||
c = memory_shouldHideMatchingItems(c);
|
||||
// Detect victory.
|
||||
c = memory_shouldDetectVictory(c);
|
||||
// See if victory has been detected.
|
||||
if (
|
||||
c.recentField == "victory" &&
|
||||
c.victory == true
|
||||
) {
|
||||
return "OK: memory_shouldDetectVictory";
|
||||
}
|
||||
return "ERR: memory_shouldDetectVictory";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
std::string memory_test_shouldHideMatchingItems(
|
||||
) {
|
||||
auto c = memory_createContext();
|
||||
c.playfieldSize = 2;
|
||||
c = memory_generateConstPlayfield(c);
|
||||
// Select two items of the same group.
|
||||
c.selectedId = 0;
|
||||
c = memory_selectItem(c);
|
||||
c.selectedId = 1;
|
||||
c = memory_selectItem(c);
|
||||
// Hide matching items.
|
||||
c = memory_shouldHideMatchingItems(c);
|
||||
// See if the two selected items match.
|
||||
if (
|
||||
c.recentField == "hiddenItems" &&
|
||||
c.hiddenItems.size() == 2 &&
|
||||
c.hiddenItems[0] == 0 &&
|
||||
c.hiddenItems[1] == 1
|
||||
) {
|
||||
return "OK: memory_shouldHideMatchingItems";
|
||||
}
|
||||
return "ERR: memory_shouldHideMatchingItems";
|
||||
}
|
||||
|
||||
15
v4/memory_test.h
Normal file
15
v4/memory_test.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#include <string>
|
||||
|
||||
#ifndef memory_test_HEADER
|
||||
#define memory_test_HEADER
|
||||
|
||||
std::string memory_test_generateConstPlayfield();
|
||||
std::string memory_test_selectItem_1x();
|
||||
std::string memory_test_selectItem_2x();
|
||||
std::string memory_test_selectItem_3x();
|
||||
std::string memory_test_shouldDeselectMismatchedItems();
|
||||
std::string memory_test_shouldDeselectMismatchedItems_itemTwice();
|
||||
std::string memory_test_shouldDetectVictory();
|
||||
std::string memory_test_shouldHideMatchingItems();
|
||||
|
||||
#endif // memory_test_HEADER
|
||||
207
v4/memory_test.py
Normal file
207
v4/memory_test.py
Normal file
@@ -0,0 +1,207 @@
|
||||
from memory import *
|
||||
from memory_Context import *
|
||||
|
||||
def memory_test_generateConstPlayfield(
|
||||
) -> str:
|
||||
c = memory_createContext()
|
||||
c.playfieldSize = 2
|
||||
c = memory_generateConstPlayfield(c)
|
||||
if (
|
||||
c.recentField == "playfieldItems" and
|
||||
len(c.playfieldItems) == 4 and
|
||||
c.playfieldItems[0] == 0 and
|
||||
c.playfieldItems[1] == 0 and
|
||||
c.playfieldItems[2] == 1 and
|
||||
c.playfieldItems[3] == 1
|
||||
):
|
||||
return "OK: memory_generateConstPlayfield"
|
||||
#}
|
||||
return "ERR: memory_generateConstPlayfield"
|
||||
#}
|
||||
|
||||
def memory_test_selectItem_1x(
|
||||
) -> str:
|
||||
c = memory_createContext()
|
||||
c.playfieldSize = 2
|
||||
c = memory_generateConstPlayfield(c)
|
||||
|
||||
# Select the first item.
|
||||
c.selectedId = 0
|
||||
c = memory_selectItem(c)
|
||||
|
||||
# See if it's in selectedItems now.
|
||||
if (
|
||||
c.recentField == "selectedItems" and
|
||||
len(c.selectedItems) == 1 and
|
||||
c.selectedItems[0] == 0
|
||||
):
|
||||
return "OK: memory_selectItem_1x"
|
||||
#}
|
||||
return "ERR: memory_selectItem_1x"
|
||||
#}
|
||||
|
||||
def memory_test_selectItem_2x(
|
||||
) -> str:
|
||||
c = memory_createContext()
|
||||
c.playfieldSize = 2
|
||||
c = memory_generateConstPlayfield(c)
|
||||
|
||||
# Select the first two items.
|
||||
c.selectedId = 0
|
||||
c = memory_selectItem(c)
|
||||
c.selectedId = 1
|
||||
c = memory_selectItem(c)
|
||||
|
||||
# See if both items are selected now.
|
||||
if (
|
||||
c.recentField == "selectedItems" and
|
||||
len(c.selectedItems) == 2 and
|
||||
c.selectedItems[0] == 0 and
|
||||
c.selectedItems[1] == 1
|
||||
):
|
||||
return "OK: memory_selectItem_2x"
|
||||
#}
|
||||
return "ERR: memory_selectItem_2x"
|
||||
#}
|
||||
|
||||
def memory_test_selectItem_3x(
|
||||
) -> str:
|
||||
c = memory_createContext()
|
||||
c.playfieldSize = 2
|
||||
c = memory_generateConstPlayfield(c)
|
||||
|
||||
# Select three items.
|
||||
c.selectedId = 0
|
||||
c = memory_selectItem(c)
|
||||
c.selectedId = 1
|
||||
c = memory_selectItem(c)
|
||||
c.selectedId = 2
|
||||
c = memory_selectItem(c)
|
||||
|
||||
# See if only one (last) item is selected now.
|
||||
if (
|
||||
c.recentField == "selectedItems" and
|
||||
len(c.selectedItems) == 1 and
|
||||
c.selectedItems[0] == 2
|
||||
):
|
||||
return "OK: memory_selectItem_3x"
|
||||
#}
|
||||
return "ERR: memory_selectItem_3x"
|
||||
#}
|
||||
|
||||
def memory_test_shouldDeselectMismatchedItems(
|
||||
) -> str:
|
||||
c = memory_createContext()
|
||||
c.playfieldSize = 2
|
||||
c = memory_generateConstPlayfield(c)
|
||||
|
||||
# Select two items of different groups.
|
||||
c.selectedId = 0
|
||||
c = memory_selectItem(c)
|
||||
c.selectedId = 2
|
||||
c = memory_selectItem(c)
|
||||
|
||||
# Detect mismatching.
|
||||
c = memory_shouldDeselectMismatchedItems(c)
|
||||
|
||||
# See if the two selected items do not match.
|
||||
if (
|
||||
c.recentField == "mismatchedItems" and
|
||||
len(c.mismatchedItems) == 2 and
|
||||
c.mismatchedItems[0] == 0 and
|
||||
c.mismatchedItems[1] == 2
|
||||
):
|
||||
return "OK: memory_shouldDeselectMismatchedItems"
|
||||
#}
|
||||
return "ERR: memory_shouldDeselectMismatchedItems"
|
||||
#}
|
||||
|
||||
def memory_test_shouldDeselectMismatchedItems_itemTwice(
|
||||
) -> str:
|
||||
c = memory_createContext()
|
||||
c.playfieldSize = 2
|
||||
c = memory_generateConstPlayfield(c)
|
||||
|
||||
# Select the same item twice.
|
||||
c.selectedId = 0
|
||||
c = memory_selectItem(c)
|
||||
c.selectedId = 0
|
||||
c = memory_selectItem(c)
|
||||
|
||||
# Detect mismatching.
|
||||
c = memory_shouldDeselectMismatchedItems(c)
|
||||
|
||||
# See if the two selected items do not match.
|
||||
if (
|
||||
c.recentField == "mismatchedItems" and
|
||||
len(c.mismatchedItems) == 1 and
|
||||
c.mismatchedItems[0] == 0
|
||||
):
|
||||
return "OK: memory_shouldDeselectMismatchedItems_itemTwice"
|
||||
#}
|
||||
return "ERR: memory_shouldDeselectMismatchedItems_itemTwice"
|
||||
#}
|
||||
|
||||
def memory_test_shouldDetectVictory(
|
||||
) -> str:
|
||||
c = memory_createContext()
|
||||
c.playfieldSize = 2
|
||||
c = memory_generateConstPlayfield(c)
|
||||
|
||||
# Select the first two items of the same group.
|
||||
c.selectedId = 0
|
||||
c = memory_selectItem(c)
|
||||
c.selectedId = 1
|
||||
c = memory_selectItem(c)
|
||||
|
||||
# Hide the first pair.
|
||||
c = memory_shouldHideMatchingItems(c)
|
||||
|
||||
# Select the last two items of the same group.
|
||||
c.selectedId = 2
|
||||
c = memory_selectItem(c)
|
||||
c.selectedId = 3
|
||||
c = memory_selectItem(c)
|
||||
|
||||
# Hide the second pair.
|
||||
c = memory_shouldHideMatchingItems(c)
|
||||
|
||||
# Detect victory.
|
||||
c = memory_shouldDetectVictory(c)
|
||||
|
||||
# See if victory has been detected.
|
||||
if (
|
||||
c.recentField == "victory" and
|
||||
c.victory == True
|
||||
):
|
||||
return "OK: memory_shouldDetectVictory"
|
||||
#}
|
||||
return "ERR: memory_shouldDetectVictory"
|
||||
#}
|
||||
|
||||
def memory_test_shouldHideMatchingItems(
|
||||
) -> str:
|
||||
c = memory_createContext()
|
||||
c.playfieldSize = 2
|
||||
c = memory_generateConstPlayfield(c)
|
||||
|
||||
# Select two items of the same group.
|
||||
c.selectedId = 0
|
||||
c = memory_selectItem(c)
|
||||
c.selectedId = 1
|
||||
c = memory_selectItem(c)
|
||||
|
||||
# Hide matching items.
|
||||
c = memory_shouldHideMatchingItems(c)
|
||||
|
||||
# See if the two selected items match.
|
||||
if (
|
||||
c.recentField == "hiddenItems" and
|
||||
len(c.hiddenItems) == 2 and
|
||||
c.hiddenItems[0] == 0 and
|
||||
c.hiddenItems[1] == 1
|
||||
):
|
||||
return "OK: memory_shouldHideMatchingItems"
|
||||
#}
|
||||
return "ERR: memory_shouldHideMatchingItems"
|
||||
#}
|
||||
186
v4/tPythonC++/CPP.py
Normal file
186
v4/tPythonC++/CPP.py
Normal file
@@ -0,0 +1,186 @@
|
||||
from Function import *
|
||||
|
||||
def includes():
|
||||
return """#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "memory.h"
|
||||
#include "memory_Context.h"
|
||||
"""
|
||||
|
||||
def replaceAnd(s):
|
||||
return s.replace("and", "&&")
|
||||
|
||||
def replaceAppend(s):
|
||||
return s.replace(".append(", ".push_back(")
|
||||
|
||||
def replaceComment(s):
|
||||
return s.replace("#", "//")
|
||||
|
||||
def replaceLen(s):
|
||||
posLen = s.find("len(")
|
||||
posEnd = s.find(")", posLen)
|
||||
if (
|
||||
posLen == -1 or
|
||||
posEnd == -1
|
||||
):
|
||||
return s
|
||||
before = s[:posLen]
|
||||
name = s[posLen + len("len("):posEnd]
|
||||
after = s[posEnd + len(")"):]
|
||||
return f"{before}{name}.size(){after}"
|
||||
|
||||
def replaceTrue(s):
|
||||
return s.replace("True", "true")
|
||||
|
||||
def translateParameter(s):
|
||||
# name: type -> type name
|
||||
parts = s.split(": ")
|
||||
indent = len(s) - len(s.lstrip())
|
||||
name = parts[0].lstrip()
|
||||
t = translateType(parts[1])
|
||||
indentation = "".join(" " * indent)
|
||||
return f"{indentation}{t} {name}"
|
||||
|
||||
def translateStatement(s, state):
|
||||
indent = len(s) - len(s.lstrip())
|
||||
indentation = "".join(" " * indent)
|
||||
ss = s.lstrip()
|
||||
posColon = ss.find(": ")
|
||||
posComma = ss.find(", ")
|
||||
posComment = ss.find("# ")
|
||||
posCtx = ss.find("c.")
|
||||
posEqual = ss.find(" = ")
|
||||
posFor = ss.find("for ")
|
||||
posIn = ss.find(" in ")
|
||||
posRange = ss.find("range(")
|
||||
posRangeEnd = ss.find("):")
|
||||
posClosingScope = ss.find("#}")
|
||||
posOpenSquareBracket = ss.find("[")
|
||||
|
||||
# # -> //
|
||||
if posComment != -1:
|
||||
return replaceComment(s)
|
||||
|
||||
# #} -> }
|
||||
if posClosingScope != -1:
|
||||
return f"{indentation}}}"
|
||||
|
||||
# for name in range(x, y): -> for (auto name = x; name < y; ++name) {
|
||||
if (
|
||||
posFor >= 0 and
|
||||
posIn >= 0 and
|
||||
posRange >= 0
|
||||
):
|
||||
name = ss[posFor + len("for "):posIn]
|
||||
x = ss[posRange + len("range("):posComma]
|
||||
y = ss[posComma + len(", "):posRangeEnd]
|
||||
return f"{indentation}for (auto {name} = {x}; {name} < {y}; ++{name}) {{"
|
||||
|
||||
# name: type = value -> type name = value
|
||||
if (
|
||||
posColon >= 0 and
|
||||
posEqual >= 0
|
||||
):
|
||||
name = ss[:posColon]
|
||||
type = ss[posColon + len(": "):posEqual]
|
||||
t = translateType(type)
|
||||
value = ss[posEqual + len(" = "):]
|
||||
return f"{indentation}{t} {name} = {value};"
|
||||
|
||||
# name = value -> auto name = value
|
||||
if (
|
||||
posCtx == -1 and
|
||||
posColon == -1 and
|
||||
posOpenSquareBracket == -1 and
|
||||
posEqual >= 0
|
||||
):
|
||||
name = ss[:posEqual]
|
||||
# Skip prepending 'auto' each time variable is assigned,
|
||||
# only do it the first time
|
||||
if name not in state.varNames:
|
||||
state.varNames[name] = True
|
||||
value = ss[posEqual + len(" = "):]
|
||||
return f"{indentation}auto {name} = {value};"
|
||||
|
||||
# Keep "if ("
|
||||
if ss == "if (":
|
||||
state.isIf = True
|
||||
return s
|
||||
|
||||
# Keep "if not ("
|
||||
if ss == "if not (":
|
||||
state.isIfNot = True
|
||||
return f"{indentation}if (!("
|
||||
|
||||
# ): -> }
|
||||
if ss == "):":
|
||||
# if
|
||||
if state.isIf:
|
||||
state.isIf = False
|
||||
return f"{indentation}) {{"
|
||||
# if not
|
||||
state.isIfNot = False
|
||||
return f"{indentation})) {{"
|
||||
|
||||
ending = ";"
|
||||
if state.isIf or state.isIfNot:
|
||||
ending = ""
|
||||
|
||||
# Unknown.
|
||||
return f"{s}{ending}"
|
||||
|
||||
def translateType(s):
|
||||
# dict[X, Y] -> std::map<X, Y>
|
||||
if s.startswith("dict["):
|
||||
kv = s[len("dict["):-len("]")]
|
||||
parts = kv.split(", ")
|
||||
return f"std::map<{parts[0]}, {parts[1]}>"
|
||||
# str -> std::string
|
||||
if s == "str":
|
||||
return "std::string"
|
||||
|
||||
# Unknown. Return as is.
|
||||
return s
|
||||
|
||||
class CPP:
|
||||
def __init__(self, fn):
|
||||
self.fn = fn
|
||||
self.isIf = False
|
||||
self.isIfNot = False
|
||||
self.varNames = {}
|
||||
|
||||
def translate(self):
|
||||
returnType = translateType(self.fn.returnType)
|
||||
|
||||
# Parameters.
|
||||
params = []
|
||||
for i in range(0, len(self.fn.parameters)):
|
||||
p = translateParameter(self.fn.parameters[i])
|
||||
# Make Context passed by reference.
|
||||
#if "Context" in p:
|
||||
# p = p.replace("Context", "Context&")
|
||||
params.append(p)
|
||||
strparams = "\n".join(params)
|
||||
if (len(strparams) > 0):
|
||||
strparams += "\n"
|
||||
|
||||
# Statements.
|
||||
sts = []
|
||||
for i in range(0, len(self.fn.statements)):
|
||||
s = translateStatement(self.fn.statements[i], self)
|
||||
s = replaceAnd(s)
|
||||
s = replaceAppend(s)
|
||||
# Replace len twice to account for double invocation.
|
||||
s = replaceLen(s)
|
||||
s = replaceLen(s)
|
||||
s = replaceTrue(s)
|
||||
sts.append(s)
|
||||
strstatements = "\n".join(sts)
|
||||
|
||||
return f"""{returnType} {self.fn.name}(
|
||||
{strparams}) {{
|
||||
{strstatements}
|
||||
}}
|
||||
"""
|
||||
|
||||
76
v4/tPythonC++/Function.py
Normal file
76
v4/tPythonC++/Function.py
Normal file
@@ -0,0 +1,76 @@
|
||||
class Function:
|
||||
def __init__(self):
|
||||
self.isBody = False
|
||||
self.isComplete = False
|
||||
self.isSignature = False
|
||||
self.name = None
|
||||
self.parameters = []
|
||||
self.returnType = None
|
||||
self.statements = []
|
||||
|
||||
def parseLine(self, ln):
|
||||
parts = ln.split(" ")
|
||||
count = len(parts)
|
||||
lastPart = parts[count - 1]
|
||||
|
||||
# Complete.
|
||||
if (
|
||||
self.isBody and
|
||||
ln.startswith("#}")
|
||||
):
|
||||
self.isComplete = True
|
||||
|
||||
# Statements.
|
||||
if (
|
||||
self.isBody and
|
||||
not ln.startswith("#}")
|
||||
):
|
||||
self.statements.append(ln)
|
||||
|
||||
# Parameters.
|
||||
if (
|
||||
self.isSignature and
|
||||
not ln.endswith(":")
|
||||
):
|
||||
p = ln
|
||||
# Remove comma if present.
|
||||
if p.endswith(","):
|
||||
p = p[:-1]
|
||||
self.parameters.append(p)
|
||||
|
||||
# Beginning of signature.
|
||||
if (
|
||||
self.returnType is None and
|
||||
self.name is None
|
||||
and lastPart.endswith("(")
|
||||
):
|
||||
self.isSignature = True
|
||||
|
||||
# Return type.
|
||||
if (
|
||||
self.isSignature and
|
||||
ln.startswith(") -> ") and
|
||||
ln.endswith(":")
|
||||
):
|
||||
self.returnType = ln[len(") -> "):-len(":")]
|
||||
|
||||
# End of parameters/signature.
|
||||
if (
|
||||
self.isSignature and
|
||||
ln.startswith(") -> ") and
|
||||
ln.endswith(":")
|
||||
):
|
||||
self.isSignature = False
|
||||
self.isBody = True
|
||||
|
||||
# Name.
|
||||
if (
|
||||
self.isSignature and
|
||||
lastPart.endswith("(")
|
||||
):
|
||||
self.name = lastPart[:-1]
|
||||
|
||||
def __repr__(self):
|
||||
return self.__str__()
|
||||
def __str__(self):
|
||||
return f"Function(name/returnT/parameters/statements: '{self.name}'/'{self.returnType}'/'{self.parameters}'/'{self.statements}')"
|
||||
37
v4/tPythonC++/process.py
Executable file
37
v4/tPythonC++/process.py
Executable file
@@ -0,0 +1,37 @@
|
||||
from CPP import *
|
||||
from Function import *
|
||||
|
||||
def process(FILE_IN):
|
||||
# Read file.
|
||||
lines_in = []
|
||||
with open(FILE_IN) as file:
|
||||
for line in file:
|
||||
lines_in.append(line.rstrip())
|
||||
|
||||
f = Function()
|
||||
out = includes()
|
||||
|
||||
# Parse.
|
||||
for ln in lines_in:
|
||||
ln = ln.rstrip()
|
||||
|
||||
# Empty line.
|
||||
if ln == "":
|
||||
out += "\n"
|
||||
# Comment.
|
||||
elif (
|
||||
ln.startswith("#") and
|
||||
not f.isBody
|
||||
):
|
||||
out += replaceComment(ln) + "\n"
|
||||
# Function.
|
||||
else:
|
||||
f.parseLine(ln)
|
||||
|
||||
if f.isComplete:
|
||||
cpp = CPP(f)
|
||||
out += cpp.translate()
|
||||
# Create new function instance.
|
||||
f = Function()
|
||||
|
||||
return out
|
||||
25
v4/tPythonC++/translate
Executable file
25
v4/tPythonC++/translate
Executable file
@@ -0,0 +1,25 @@
|
||||
#!/usr/bin/env python3
|
||||
import os
|
||||
import sys
|
||||
from process import *
|
||||
|
||||
DIR = os.path.dirname(os.path.realpath(sys.argv[0]))
|
||||
|
||||
if len(sys.argv) < 2:
|
||||
print("Usage: /path/to/translate [OPTIONS] PYTHON_FILE")
|
||||
sys.exit(1)
|
||||
|
||||
FILE_IN = sys.argv[-1]
|
||||
|
||||
# Parse options
|
||||
# TODO Use options
|
||||
OPT_HEADER = "--header" in sys.argv
|
||||
OPT_INCLUDES = None
|
||||
OPT_PREFIX_INCLUDES = "--includes="
|
||||
for arg in sys.argv:
|
||||
if arg.startswith(OPT_PREFIX_INCLUDES):
|
||||
OPT_INCLUDES = arg[len(OPT_PREFIX_INCLUDES):]
|
||||
|
||||
# Translate file.
|
||||
out = process(FILE_IN, OPT_HEADER, OPT_INCLUDES)
|
||||
print(out)
|
||||
7
v4/translate-py-cxx
Executable file
7
v4/translate-py-cxx
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
DIR=$(cd "$(dirname "$0")" ; pwd -P)
|
||||
TR=$DIR/tPythonC++/translate
|
||||
|
||||
$TR $DIR/memory.py > $DIR/memory.cpp
|
||||
$TR $DIR/memory_test.py > $DIR/memory_test.cpp
|
||||
Reference in New Issue
Block a user