Added Dockerfile and sources

This commit is contained in:
0xFEEDC0DE64
2018-05-06 02:35:19 +02:00
parent 86afb42141
commit ae8e130996
5 changed files with 349 additions and 29 deletions

4
.dockerignore Normal file
View File

@@ -0,0 +1,4 @@
/.gitignore
/Dockerfile
/LICENSE
/README.md

92
.gitignore vendored
View File

@@ -1,39 +1,73 @@
# C++ objects and libs
# This file is used to ignore files which are generated
# ----------------------------------------------------------------------------
*.slo
*.lo
*.o
*~
*.autosave
*.a
*.la
*.lai
*.core
*.moc
*.o
*.obj
*.orig
*.rej
*.so
*.dll
*.dylib
# Qt-es
*.so.*
*_pch.h.cpp
*_resource.rc
*.qm
.#*
*.*#
core
!core/
tags
.DS_Store
.directory
*.debug
Makefile*
*.prl
*.app
moc_*.cpp
ui_*.h
qrc_*.cpp
Thumbs.db
*.res
*.rc
/.qmake.cache
/.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
*.qmlproject.user
*.qmlproject.user.*
# Vim temporary files
.*.swp
# QtCtreator CMake
CMakeLists.txt.user*
# Visual Studio generated files
*.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
View 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
View 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
View 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