Added Dockerfile and sources
This commit is contained in:
4
.dockerignore
Normal file
4
.dockerignore
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
/.gitignore
|
||||||
|
/Dockerfile
|
||||||
|
/LICENSE
|
||||||
|
/README.md
|
92
.gitignore
vendored
92
.gitignore
vendored
@@ -1,39 +1,73 @@
|
|||||||
# C++ objects and libs
|
# This file is used to ignore files which are generated
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
|
||||||
*.slo
|
*~
|
||||||
*.lo
|
*.autosave
|
||||||
*.o
|
|
||||||
*.a
|
*.a
|
||||||
*.la
|
*.core
|
||||||
*.lai
|
*.moc
|
||||||
|
*.o
|
||||||
|
*.obj
|
||||||
|
*.orig
|
||||||
|
*.rej
|
||||||
*.so
|
*.so
|
||||||
*.dll
|
*.so.*
|
||||||
*.dylib
|
*_pch.h.cpp
|
||||||
|
*_resource.rc
|
||||||
# Qt-es
|
*.qm
|
||||||
|
.#*
|
||||||
|
*.*#
|
||||||
|
core
|
||||||
|
!core/
|
||||||
|
tags
|
||||||
|
.DS_Store
|
||||||
|
.directory
|
||||||
|
*.debug
|
||||||
|
Makefile*
|
||||||
|
*.prl
|
||||||
|
*.app
|
||||||
|
moc_*.cpp
|
||||||
|
ui_*.h
|
||||||
|
qrc_*.cpp
|
||||||
|
Thumbs.db
|
||||||
|
*.res
|
||||||
|
*.rc
|
||||||
/.qmake.cache
|
/.qmake.cache
|
||||||
/.qmake.stash
|
/.qmake.stash
|
||||||
*.pro.user
|
|
||||||
*.pro.user.*
|
|
||||||
*.qbs.user
|
|
||||||
*.qbs.user.*
|
|
||||||
*.moc
|
|
||||||
moc_*.cpp
|
|
||||||
moc_*.h
|
|
||||||
qrc_*.cpp
|
|
||||||
ui_*.h
|
|
||||||
Makefile*
|
|
||||||
*build-*
|
|
||||||
|
|
||||||
# QtCreator
|
# qtcreator generated files
|
||||||
|
*.pro.user*
|
||||||
|
|
||||||
*.autosave
|
# xemacs temporary files
|
||||||
|
*.flc
|
||||||
|
|
||||||
# QtCtreator Qml
|
# Vim temporary files
|
||||||
*.qmlproject.user
|
.*.swp
|
||||||
*.qmlproject.user.*
|
|
||||||
|
|
||||||
# QtCtreator CMake
|
# Visual Studio generated files
|
||||||
CMakeLists.txt.user*
|
*.ib_pdb_index
|
||||||
|
*.idb
|
||||||
|
*.ilk
|
||||||
|
*.pdb
|
||||||
|
*.sln
|
||||||
|
*.suo
|
||||||
|
*.vcproj
|
||||||
|
*vcproj.*.*.user
|
||||||
|
*.ncb
|
||||||
|
*.sdf
|
||||||
|
*.opensdf
|
||||||
|
*.vcxproj
|
||||||
|
*vcxproj.*
|
||||||
|
|
||||||
|
# MinGW generated files
|
||||||
|
*.Debug
|
||||||
|
*.Release
|
||||||
|
|
||||||
|
# Python byte code
|
||||||
|
*.pyc
|
||||||
|
|
||||||
|
# Binaries
|
||||||
|
# --------
|
||||||
|
*.dll
|
||||||
|
*.exe
|
||||||
|
|
||||||
|
31
Dockerfile
Normal file
31
Dockerfile
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
FROM ubuntu:artful
|
||||||
|
|
||||||
|
RUN ln -snf /usr/share/zoneinfo/Europe/Vienna /etc/localtime && echo Europe/Vienna > /etc/timezone
|
||||||
|
|
||||||
|
RUN apt update \
|
||||||
|
&& apt install tzdata -y \
|
||||||
|
&& rm /var/lib/apt/lists/* /var/log/* -Rf
|
||||||
|
|
||||||
|
RUN apt update \
|
||||||
|
&& apt install libssl1.0.0 ca-certificates libqt5core5a libqt5gui5 libqt5network5 libqt5multimedia5 -y \
|
||||||
|
&& rm /var/lib/apt/lists/* /var/log/* -Rf
|
||||||
|
|
||||||
|
RUN apt update \
|
||||||
|
&& apt install git-core g++ make qt5-default qtmultimedia5-dev qttools5-dev qttools5-dev-tools -y \
|
||||||
|
&& rm /var/lib/apt/lists/* /var/log/* -Rf
|
||||||
|
|
||||||
|
ADD . /tmp/tictactoe-web
|
||||||
|
|
||||||
|
RUN mkdir -p /tmp/build_tictactoe-web \
|
||||||
|
&& qmake /tmp/tictactoe-web -o /tmp/build_tictactoe-web/Makefile -config release \
|
||||||
|
&& make -C /tmp/build_tictactoe-web -j8 \
|
||||||
|
&& make -C /tmp/build_tictactoe-web install
|
||||||
|
|
||||||
|
RUN cd /tmp/build_tictactoe-web \
|
||||||
|
&& ./tictactoe-web
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
FROM httpd:2.4
|
||||||
|
|
||||||
|
COPY --from=0 /tmp/build_tictactoe-web/files /usr/local/apache2/htdocs
|
242
main.cpp
Executable file
242
main.cpp
Executable file
@@ -0,0 +1,242 @@
|
|||||||
|
#include <QCoreApplication>
|
||||||
|
#include <QDir>
|
||||||
|
#include <QFile>
|
||||||
|
#include <QTextStream>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
enum class FieldType { EMPTY, CIRCLE, CROSS };
|
||||||
|
|
||||||
|
char fieldTypeLetter(const FieldType fieldType)
|
||||||
|
{
|
||||||
|
switch(fieldType)
|
||||||
|
{
|
||||||
|
case FieldType::EMPTY: return '_';
|
||||||
|
case FieldType::CIRCLE: return 'O';
|
||||||
|
case FieldType::CROSS: return 'X';
|
||||||
|
default: qFatal("unexpected field type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::size_t WIDTH, std::size_t HEIGHT>
|
||||||
|
QString getFieldName(const std::array<std::array<FieldType, WIDTH>, HEIGHT> &field)
|
||||||
|
{
|
||||||
|
QString result;
|
||||||
|
|
||||||
|
for(int y = 0; y < HEIGHT; y++)
|
||||||
|
{
|
||||||
|
const auto &row = field.at(y);
|
||||||
|
|
||||||
|
if(!result.isEmpty())
|
||||||
|
result.append('-');
|
||||||
|
|
||||||
|
for(int x = 0; x < WIDTH; x++)
|
||||||
|
result.append(fieldTypeLetter(row.at(x)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::size_t WIDTH, std::size_t HEIGHT>
|
||||||
|
quint64 getFieldHash(const std::array<std::array<FieldType, WIDTH>, HEIGHT> &field)
|
||||||
|
{
|
||||||
|
quint64 result = 0;
|
||||||
|
quint64 digitValue = 1;
|
||||||
|
|
||||||
|
for(quint32 y = 0; y < HEIGHT; y++)
|
||||||
|
for(quint32 x = 0; x < WIDTH; x++)
|
||||||
|
{
|
||||||
|
quint8 digit = (quint8)field.at(y).at(x);
|
||||||
|
|
||||||
|
result += digit * digitValue;
|
||||||
|
|
||||||
|
digitValue *= 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::size_t SIZE>
|
||||||
|
FieldType getFieldWinner(const std::array<std::array<FieldType, SIZE>, SIZE> &field)
|
||||||
|
{
|
||||||
|
for(quint32 y = 0; y < SIZE; y++)
|
||||||
|
{
|
||||||
|
const auto &row = field.at(y);
|
||||||
|
auto last = row.at(0);
|
||||||
|
|
||||||
|
if(last != FieldType::EMPTY)
|
||||||
|
{
|
||||||
|
auto failed = false;
|
||||||
|
for(quint32 x = 1; x < SIZE; x++)
|
||||||
|
{
|
||||||
|
if(row.at(x) != last)
|
||||||
|
{
|
||||||
|
failed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
last = row.at(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!failed)
|
||||||
|
return last;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(quint32 x = 0; x < SIZE; x++)
|
||||||
|
{
|
||||||
|
auto last = field.at(0).at(SIZE-1);
|
||||||
|
|
||||||
|
if(last != FieldType::EMPTY)
|
||||||
|
{
|
||||||
|
auto failed = false;
|
||||||
|
for(quint32 y = 1; y < SIZE; y++)
|
||||||
|
{
|
||||||
|
if(field.at(y).at(x) != last)
|
||||||
|
{
|
||||||
|
failed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
last = field.at(y).at(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!failed)
|
||||||
|
return last;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto last = field.at(0).at(0);
|
||||||
|
|
||||||
|
if(last != FieldType::EMPTY)
|
||||||
|
{
|
||||||
|
auto failed = false;
|
||||||
|
for(quint32 i = 1; i < SIZE; i++)
|
||||||
|
{
|
||||||
|
if(field.at(i).at(i) != last)
|
||||||
|
{
|
||||||
|
failed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
last = field.at(i).at(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!failed)
|
||||||
|
return last;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto last = field.at(0).at(SIZE-1);
|
||||||
|
|
||||||
|
if(last != FieldType::EMPTY)
|
||||||
|
{
|
||||||
|
auto failed = false;
|
||||||
|
for(quint32 i = 1; i < SIZE; i++)
|
||||||
|
{
|
||||||
|
if(field.at(i).at(SIZE - i) != last)
|
||||||
|
{
|
||||||
|
failed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
last = field.at(i).at(SIZE - i);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!failed)
|
||||||
|
return last;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return FieldType::EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::size_t WIDTH, std::size_t HEIGHT>
|
||||||
|
QString writeField(const QDir &dir, const std::array<std::array<FieldType, WIDTH>, HEIGHT> &field)
|
||||||
|
{
|
||||||
|
const auto fieldHash = getFieldHash(field);
|
||||||
|
const auto name = (fieldHash == 0 ? QStringLiteral("index") : QString::number(fieldHash)) + ".html";
|
||||||
|
|
||||||
|
qDebug() << "writing" << name;
|
||||||
|
|
||||||
|
QFile file(dir.absoluteFilePath(name));
|
||||||
|
|
||||||
|
if(file.exists())
|
||||||
|
return name;
|
||||||
|
|
||||||
|
auto winner = getFieldWinner(field);
|
||||||
|
|
||||||
|
const auto fieldPlayer = std::count(std::begin(field.at(0)), std::end(field.at(2)), FieldType::CIRCLE) <
|
||||||
|
std::count(std::begin(field.at(0)), std::end(field.at(2)), FieldType::CROSS) ?
|
||||||
|
FieldType::CIRCLE : FieldType::CROSS;
|
||||||
|
|
||||||
|
if(!file.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text))
|
||||||
|
qFatal("Could not open file");
|
||||||
|
|
||||||
|
QTextStream textStream(&file);
|
||||||
|
textStream << "<table border=\"1\">" << endl;
|
||||||
|
|
||||||
|
for(quint32 y = 0; y < HEIGHT; y++)
|
||||||
|
{
|
||||||
|
const auto &row = field.at(y);
|
||||||
|
|
||||||
|
textStream << "<tr>" << endl;
|
||||||
|
|
||||||
|
for(quint32 x = 0; x < WIDTH; x++)
|
||||||
|
{
|
||||||
|
textStream << "<td>";
|
||||||
|
|
||||||
|
if(row.at(x) == FieldType::EMPTY && winner == FieldType::EMPTY)
|
||||||
|
{
|
||||||
|
auto copy = field;
|
||||||
|
copy[y][x] = fieldPlayer;
|
||||||
|
const auto otherName = writeField(dir, copy);
|
||||||
|
textStream << "<a href=\"" << otherName << "\">_</a>";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
textStream << fieldTypeLetter(row.at(x));
|
||||||
|
|
||||||
|
textStream << "</td>" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
textStream << "</tr>" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
textStream << "</table>" << endl;
|
||||||
|
|
||||||
|
switch(winner)
|
||||||
|
{
|
||||||
|
case FieldType::CIRCLE:
|
||||||
|
textStream << "<span style=\"font-size: 2em;\">CIRCLE won</span>" << endl;
|
||||||
|
break;
|
||||||
|
case FieldType::CROSS:
|
||||||
|
textStream << "<span style=\"font-size: 2em;\">CROSS won</span>" << endl;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
switch(fieldPlayer)
|
||||||
|
{
|
||||||
|
case FieldType::CIRCLE:
|
||||||
|
textStream << "<span style=\"font-size: 2em;\">CIRCLE plays</span>" << endl;
|
||||||
|
break;
|
||||||
|
case FieldType::CROSS:
|
||||||
|
textStream << "<span style=\"font-size: 2em;\">CROSS plays</span>" << endl;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
qt_noop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
QCoreApplication a(argc, argv);
|
||||||
|
|
||||||
|
QDir dir("files");
|
||||||
|
dir.removeRecursively();
|
||||||
|
dir.mkpath(dir.absolutePath());
|
||||||
|
|
||||||
|
std::array<std::array<FieldType, 3>, 3> test {};
|
||||||
|
writeField(dir, test);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
9
tictactoe-web.pro
Executable file
9
tictactoe-web.pro
Executable file
@@ -0,0 +1,9 @@
|
|||||||
|
QT = core
|
||||||
|
|
||||||
|
CONFIG += c++11
|
||||||
|
|
||||||
|
DEFINES += QT_DEPRECATED_WARNINGS QT_DISABLE_DEPRECATED_BEFORE=0x060000
|
||||||
|
|
||||||
|
SOURCES += main.cpp
|
||||||
|
|
||||||
|
OTHER_FILES += Dockerfile
|
Reference in New Issue
Block a user