aboutsummaryrefslogtreecommitdiff
path: root/week09/Exam1
diff options
context:
space:
mode:
authorSyndamia <kamen@syndamia.com>2024-04-22 13:52:55 +0300
committerSyndamia <kamen@syndamia.com>2024-04-22 13:52:55 +0300
commitf7ed9a8a6c31b17d54d2f37cc0f12b64f8e4b6d2 (patch)
tree866abf46779f63a2fd1c8cfc70f7ff5f3bc11752 /week09/Exam1
parenta2e284b0056075e2365deaa2455be567c3b3c945 (diff)
downloadoop-2023-solutions-f7ed9a8a6c31b17d54d2f37cc0f12b64f8e4b6d2.tar
oop-2023-solutions-f7ed9a8a6c31b17d54d2f37cc0f12b64f8e4b6d2.tar.gz
oop-2023-solutions-f7ed9a8a6c31b17d54d2f37cc0f12b64f8e4b6d2.zip
[w9] Added exercise descriptions and solution to exam 1
Diffstat (limited to 'week09/Exam1')
-rw-r--r--week09/Exam1/Drone.cpp140
-rw-r--r--week09/Exam1/Drone.h34
-rw-r--r--week09/Exam1/DroneShow.cpp100
-rw-r--r--week09/Exam1/DroneShow.h28
-rw-r--r--week09/Exam1/main.cpp79
5 files changed, 381 insertions, 0 deletions
diff --git a/week09/Exam1/Drone.cpp b/week09/Exam1/Drone.cpp
new file mode 100644
index 0000000..6895a74
--- /dev/null
+++ b/week09/Exam1/Drone.cpp
@@ -0,0 +1,140 @@
+#include "Drone.h"
+#include <cstring>
+#include <fstream>
+#include <iostream>
+
+/* Голяма четворка */
+
+void Drone::free() {
+ delete[] id;
+}
+void Drone::copyFrom(const Drone& other) {
+ id = new char[strlen(other.id) + 1];
+ strcpy(id, other.id);
+ strcpy(generatedPath, other.generatedPath);
+ position = other.position;
+}
+
+Drone::Drone() {
+ id = nullptr;
+ generatedPath[0] = '\0';
+ position = 0;
+}
+Drone::~Drone() {
+ free();
+}
+Drone::Drone(const Drone& other) {
+ copyFrom(other);
+}
+Drone& Drone::operator=(const Drone& other) {
+ if (this != &other) {
+ free();
+ copyFrom(other);
+ }
+ return *this;
+}
+
+/* Move семантики */
+
+Drone::Drone(Drone&& other) {
+ id = other.id;
+ other.id = nullptr;
+
+ strcpy(generatedPath, other.generatedPath);
+ position = other.position;
+}
+
+Drone& Drone::operator=(Drone&& other) {
+ if (this != &other) {
+ free();
+
+ id = other.id;
+ other.id = nullptr;
+
+ strcpy(generatedPath, other.generatedPath);
+ position = other.position;
+ }
+ return *this;
+}
+
+/* Метод от 1.2 */
+void Drone::printGeneratedPath() {
+ std::ifstream inFile(generatedPath, std::ios::binary);
+ if (!inFile.is_open()) {
+ throw "Could not open generatedPath!"; // ок е и вместо това да се направи "return;"
+ }
+
+ while(!inFile.eof()) {
+ double x, y;
+ // Не е казано формата на този файл какъв е, затова допускаме най-простия възможен:
+ // една голяма последователност от double-и, първия е х1, втория е y1, третия е x2, четвъртия е y2 и так. нат.
+ inFile.read((char*)&x, sizeof(x));
+ inFile.read((char*)&y, sizeof(y));
+
+ std::cout << x << ", " << y << std::endl;
+ }
+
+ inFile.close();
+}
+
+/* Метод от 1.2 */
+Coordinate Drone::moveWithOneStep() {
+ std::ifstream inFile(generatedPath, std::ios::binary);
+ if (!inFile.is_open()) {
+ throw "Could not open generatedPath!"; // ок е вместо това да бъде "return;"
+ }
+
+ double x, y;
+ for (int i = 0; i <= position + 1 && !inFile.eof(); i++) {
+ inFile.read((char*)&x, sizeof(x));
+ inFile.read((char*)&y, sizeof(y));
+ }
+ // Ако във файла не съществува координат на position+1
+ if (inFile.eof()) {
+ inFile.close();
+ throw "No next position";
+ }
+
+ std::cout << x << ", " << y << std::endl;
+
+ position++;
+ inFile.close();
+ return { x, y }; // Еквивалентно на "return Coordinate({ x, y });"
+}
+
+/* Помощна за 2.2, метод play */
+// Кодът е почти еднакъв с moveWithOneStep, обаче при moveWithOneStep първо местим и връщаме новата позиция,
+// докато тук връщаме сегашната и след това местим
+// Хубаво е логиката да се изкара в някаква обща член-функция, но като за контролно така е коректно
+Coordinate Drone::positionAndMove() {
+ std::ifstream inFile(generatedPath, std::ios::binary);
+ if (!inFile.is_open()) {
+ throw "Could not open generatedPath!"; // ок е вместо това да бъде "return;"
+ }
+
+ double x, y;
+ // vvvvvvvvvvv ето тук е единствената разлика с moveWithOneStep
+ for (int i = 0; i <= position && !inFile.eof(); i++) {
+ inFile.read((char*)&x, sizeof(x));
+ inFile.read((char*)&y, sizeof(y));
+ }
+ // Ако във файла не съществува координат на position+1
+ if (inFile.eof()) {
+ inFile.close();
+ throw "No next position";
+ }
+
+ std::cout << x << ", " << y << std::endl;
+
+ position++;
+ inFile.close();
+ return { x, y }; // Еквивалентно на "return Coordinate({ x, y });"
+}
+
+/* Помощна за 3.1 */
+Drone::Drone(const char* id, char generatedPath[64], int position) {
+ this->id = new char[strlen(id)+1];
+ strcpy(this->id, id);
+ strcpy(this->generatedPath, generatedPath);
+ this->position = position;
+}
diff --git a/week09/Exam1/Drone.h b/week09/Exam1/Drone.h
new file mode 100644
index 0000000..a45cceb
--- /dev/null
+++ b/week09/Exam1/Drone.h
@@ -0,0 +1,34 @@
+// Помощна структура за метода moveWithOneStep
+struct Coordinate {
+ double x;
+ double y;
+};
+
+class Drone {
+ // +0.25 За член данни
+ char* id;
+ char generatedPath[64];
+ // Валидна интерпретация е position да бъде индекс, нищо не му противоречи
+ int position;
+
+ // +1.25 За голяма петица
+ void free();
+ void copyFrom(const Drone& other);
+public:
+ Drone();
+ ~Drone();
+ Drone(const Drone& other);
+ Drone& operator=(const Drone& other);
+ Drone(Drone&& other);
+ Drone& operator=(Drone&& other);
+
+ // +0.50 За метод
+ void printGeneratedPath();
+ // +0.50 За метод
+ Coordinate moveWithOneStep();
+
+ // Помощна за 2.2, метод play
+ Coordinate positionAndMove();
+ // Помощна за 3.1
+ Drone(const char* id, char generatedPath[64], int position);
+};
diff --git a/week09/Exam1/DroneShow.cpp b/week09/Exam1/DroneShow.cpp
new file mode 100644
index 0000000..aaffc8f
--- /dev/null
+++ b/week09/Exam1/DroneShow.cpp
@@ -0,0 +1,100 @@
+#include "DroneShow.h"
+#include <iostream>
+#include <cstring>
+
+/* Голяма петица */
+void DroneShow::free() {
+ delete[] name;
+for (int i = 0; i < 1024; i++) {
+ delete drones[i];
+ }
+}
+void DroneShow::copyFrom(const DroneShow& other) {
+ name = new char[strlen(other.name) + 1];
+ strcpy(name, other.name);
+ for (int i = 0; i < 1024; i++) {
+ drones[i] = new Drone(*other.drones[i]);
+ }
+}
+
+DroneShow::DroneShow() {
+ name = nullptr;
+ for (int i = 0; i < 1024; i++) {
+ drones[i] = nullptr;
+ }
+}
+
+DroneShow::~DroneShow() {
+ free();
+}
+
+DroneShow::DroneShow(const DroneShow& other) {
+ copyFrom(other);
+}
+
+DroneShow& DroneShow::operator=(const DroneShow& other) {
+ if (this != &other) {
+ free();
+ copyFrom(other);
+ }
+ return *this;
+}
+
+DroneShow::DroneShow(DroneShow&& other) {
+ this->name = other.name;
+ other.name = nullptr;
+
+ for (int i = 0; i < 1024; i++) {
+ this->drones[i] = other.drones[i];
+ other.drones[i] = nullptr;
+ }
+}
+
+DroneShow& DroneShow::operator=(DroneShow&& other) {
+ if (this != &other) {
+ free();
+
+ this->name = other.name;
+ other.name = nullptr;
+
+ for (int i = 0; i < 1024; i++) {
+ this->drones[i] = other.drones[i];
+ other.drones[i] = nullptr;
+ }
+ }
+ return *this;
+}
+
+/* Метод от 2.2 */
+bool DroneShow::isEmpty(int index) {
+ return drones[index] == nullptr;
+}
+
+/* Конструктор от 2.2 */
+DroneShow::DroneShow(const char* name, Drone* drones[1024]) {
+ this->name = new char[strlen(name) + 1];
+ strcpy(this->name, name);
+ for (int i = 0; i < 1024; i++) {
+ this->drones[i] = new Drone(*drones[i]); // Директно извикваме копиращия конструктор
+ }
+}
+
+/* Метод от 2.2 */
+void DroneShow::play() {
+ try {
+ while(true) { // за всяка стъпка от шоуто
+ for (int i = 0; i < 1024; i++) { // за всеки дрон
+ if (isEmpty(i)) continue; // правим го за да не пишем код в още къдрави скоби
+
+ // Всички дронове имат еднакъв брой въведени позиции, тоест първият дрон,
+ // който се опита да отиде на следваща несъществуваща позиция ще хвърли грешка и това описва
+ // края на шоуто
+ Coordinate c = drones[i]->positionAndMove();
+ std::cout << c.x << ", " << c.y << std::endl;
+ }
+ }
+ }
+ catch(const char* error) {
+ // Няма какво да правим по условие
+ }
+}
diff --git a/week09/Exam1/DroneShow.h b/week09/Exam1/DroneShow.h
new file mode 100644
index 0000000..fd7e880
--- /dev/null
+++ b/week09/Exam1/DroneShow.h
@@ -0,0 +1,28 @@
+#include "Drone.h"
+
+class DroneShow {
+ char* name; // ок ако има голяма петица и нужните проверки, иначе трябва да е "char name[128]"
+ // масив от указатели, ако е nullptr значи няма дрон, иначе има
+ // това е по-добра интерпретация от това във всеки дрон да пазим "isEmpty" булева стойност или подобно, понеже
+ // пише че на позиция може да *няма* дрон, тоест аргумент е ако има дефолтен дрон пак да кажем, че има
+ Drone* drones[1024];
+
+ // Голямата петица не дава директно точки, но отнема
+ // Щом имаме динамична памет, тогава ЗАДЪЛЖИТЕЛНО трябва да имаме голяма петица
+ void free();
+ void copyFrom(const DroneShow& other);
+public:
+ DroneShow();
+ ~DroneShow();
+ DroneShow(const DroneShow& other);
+ DroneShow& operator=(const DroneShow& other);
+ DroneShow(DroneShow&& other);
+ DroneShow& operator=(DroneShow&& other);
+
+ // +0.15 за метод
+ bool isEmpty(int index);
+ // +0.50 за конструктор; не са ни дадени ограничения, затова правим възможно най-простия такъв
+ DroneShow(const char* name, Drone* drones[1024]);
+ // +0.35 за метод
+ void play();
+};
diff --git a/week09/Exam1/main.cpp b/week09/Exam1/main.cpp
new file mode 100644
index 0000000..1d62051
--- /dev/null
+++ b/week09/Exam1/main.cpp
@@ -0,0 +1,79 @@
+#include "DroneShow.h"
+#include <iostream>
+#include <fstream>
+
+/* Относно условието с dronesPath.txt, напълно валидна интерпретация е, че просто
+ * пренасяме информация от файл на име dronesPath.txt в друг с име, въведено от потребителя.
+ * Друга интерпретация е, че пътищата трябва да се изкарат в различни файлове за всеки дрон, или пък
+ * да разширим Drone класа, така че да работи с такъв файл или с директен обект който пази пътя.
+ *
+ * Всички тези са валидни, ако се зачетете в условието, нищо което е директно казано не противоречи,
+ * на вас остава да решите кое искате да имплементирайте.
+ * На мен ми се струва, че първото изисква възможно най-малко труд, така че това съм направил.
+ */
+void dronesPathLogic() {
+ std::ifstream inFile("dronesPath.txt");
+ if (!inFile.is_open()) return;
+
+ char outName[1024];
+ std::cin.getline(outName, 1024);
+
+ std::ofstream outFile(outName, std::ios::binary);
+ if (!outFile.is_open()) return;
+
+ while(!inFile.eof()) { // за всеки път в dronesPath.txt
+ int currentSize = 0;
+
+ // Намираме дължината на сегашния път
+ // Възможно е да го напрваим с оразмеряващ се масив в който пълним всички координати, но това ми се струва повече писане
+ int startPos = inFile.peek();
+ while (inFile.peek() != '\n' && !inFile.eof()) { // докато не сме стигнали края на пътя
+ currentSize++;
+ double x, y;
+ inFile >> x >> y; // "пропускаме" сегашния координат
+ }
+ inFile.clear(); // Ако сме стигнали края на файла, fail флагът ще бъде вдигнат, така го сваляме
+ inFile.seekg(startPos, std::ios::beg); // Намерили сме дължината, но сега ще трябва да изкараме всички координати
+
+ // Не е казано как трябва да изглежда файла в който пишем, затова правим най-простото нещо:
+ // първо пишем дължината на пътя (брой координати) и след това толкова на брой координати
+ // Имайки предвид, че е двоичен, не можем да имаме разделител ей-така, за да определим кога
+ // един път почва и друг свършва.
+ outFile.write((char*)&currentSize, sizeof(currentSize));
+
+ while (inFile.peek() != '\n' && !inFile.eof()) {
+ double x, y;
+ inFile >> x >> y;
+ outFile.write((char*)&x, sizeof(x));
+ outFile.write((char*)&y, sizeof(y));
+ }
+ }
+
+ inFile.close();
+ outFile.close();
+}
+
+int main() {
+ char bufferName[1024], bufferGeneratedPath[1024];
+ Drone* drones[1024];
+
+ for (int i = 0; i < 1024; i++) {
+ std::cin.getline(bufferName, 1024);
+ std::cin.getline(bufferGeneratedPath, 1024);
+ int position;
+ std::cin >> position;
+ std::cin.ignore();
+
+ drones[i] = new Drone(bufferName, bufferGeneratedPath, position);
+ }
+
+ dronesPathLogic();
+
+ std::cin.getline(bufferName, 1024);
+ DroneShow ds(bufferName, drones);
+ ds.play();
+
+ for(int i = 0; i < 1024; i++) {
+ delete drones[i];
+ }
+}