diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..eac927d --- /dev/null +++ b/Dockerfile @@ -0,0 +1,33 @@ +# Base image with g++ and build tools +FROM ubuntu:22.04 + +# Prevent prompts from tzdata +ENV DEBIAN_FRONTEND=noninteractive + +# Install dependencies +RUN apt-get update && apt-get install -y \ + g++ \ + make \ + build-essential \ + nano \ + cmake \ + git \ + && rm -rf /var/lib/apt/lists/* + +# Create app directory +WORKDIR /app + +# Copy all project files to /app in container +COPY . . + +# Compile the code +RUN make + +# Set the default command to run the compiled app +CMD ["./Netflix"] + +# Build Docker Image +docker build -t netflix-app . + +# Run Docker Image +docker run -it netflix-app diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..732f38c --- /dev/null +++ b/Makefile @@ -0,0 +1,16 @@ +CXX = g++ +CXXFLAGS = -std=c++17 -Wall +SOURCES = main.cpp user.cpp admin.cpp content.cpp persistence.cpp init_content.cpp +OBJECTS = $(SOURCES:.cpp=.o) +TARGET = Netflix + +all: $(TARGET) + +$(TARGET): $(OBJECTS) + $(CXX) $(CXXFLAGS) -o $(TARGET) $(OBJECTS) + +%.o: %.cpp + $(CXX) $(CXXFLAGS) -c $< -o $@ + +clean: + rm -f *.o $(TARGET) diff --git a/OverTheWire_Bandit_upto_15.md b/OverTheWire_Bandit_upto_15.md new file mode 100644 index 0000000..3430d28 --- /dev/null +++ b/OverTheWire_Bandit_upto_15.md @@ -0,0 +1,413 @@ +Level 0 : +**Username : bandit0** +```bash +ssh bandit0@bandit.labs.overthewire.org -p 2220 +``` +**password : bandit0** + +### Level 0 to Level 1 +```bash +ls -alps +``` +> lists all the directory contents of bandit0 +```bash +cat readme +``` +> gives the password to the next level stored in the readme directory +exit and login to bandit1 using ssh as did in Level 0 +**password : ZjLjTmM6FvvyRnrb2rfNWOZOTa6ip5If** + +### Level 1 to Level 2 +```bash +ls -alps +``` +> lists all the directory contents of bandit1 +```bash +cat./- +``` +> We cannot directly write cat - because then the compiler does not give output as there is no filename after - thats why we use ./ and then filename - and now we get the password for next level +exit and login to next level using ssh +**password : 263JGJPfgU6LtdEvgfWU1XP5yac29mFx** + +### Level 2 to Level 3 +```bash +ls -alps +``` +> lists all the directory contents of bandit2 +```bash +cat spaces\ in\ this\ filename +``` +> \ takes in account the spaces in the name of the file "spaces in this filename" and hence we get the password for next level +exit and login to next level using ssh. +**password : MNk8KNH3Usiio41PRUEoDFPqfxLPlSmx** + +### Level 3 to Level 4 +```bash +ls -alps +``` +> lists all the directory contents of bandit3 +```bash +cd inhere/ +``` +> changes the working directory to inhere +```bash +ls -alps +``` +> lists all the directory contents of inhere +```bash +cat ...Hiding-From-You +``` +> gives password of the next level from the hidden file +exit and login to next level using ssh +**password : 2WmrDFRmJIq3IPxneAaMGhap0pFhF3NJ** + +### Level 4 to Level 5 +```bash +ls -alps +``` +> lists all the directory contents of bandit4 +```bash +cd inhere/ +``` +> changes the working directory to inhere +```bash +ls -alps +``` +> lists all the directory contents of inhere +```bash +file ./* +``` +> finds the human readable file in inhere directory and indicates it as ASCII text +```bash +cat ./-file07 +``` +> gives the password from the human readable file for the next level +exit and login to next level using ssh +**password : 4oQYVPkxZOOEOO5pTW81FB8j8lxXGUQw** + +### Level 5 to Level 6 +```bash +ls -alps +``` +> lists all the directory contents of bandit5 +```bash +cd inhere/ +``` +> changes the working directory to inhere +```bash +ls -alps +``` +> lists all the directory contents of inhere +```bash +find ~/inhere ! -executable -size 1033c +``` +> finds the required file with size 1033 bytes and which is human readable and not executable +```bash +cat /home/bandit5/inhere/maybehere07/.file2 +``` +> gives the password stored in the file found above +exit and login to next level using ssh +**password : HWasnPhtq9AVKe0dmk45nxy20cvUa6EG** + +### Level 6 to Level 7 +```bash +find / -user bandit7 -group bandit6 -size 33c +``` +> finds the file address of the file owned by user bandit7 and group bandit6 and of size 33 bytes +```bash +cat /var/lib/dpkg/info/bandit7.password +``` +> gives the password stored in the file found above +**password : morbNTDkSW6jIlUc0ymOdMaLnOlFVAaj** +exit and login to next level using ssh + +### Level 7 to Level 8 +```bash +ls -alps +``` +> lists all the directory contents of bandit7 +```bash +cat data.txt +``` +> gives the contents of the file data.txt +```bash +grep millionth data.txt +``` +> gives the password next to the word millionth in data.txt +exit and login to next level using ssh +**password : dfwvzFQi4mU0wfNbFOe9RoWskMLg7eEc** + +### Level 8 to Level 9 +```bash +ls -alps +``` +> lists all the directory contents of bandit8 +```bash +cat data.txt +``` +> gives the contents of the file data.txt +```bash +sort data.txt | uniq -u +``` +> sorts the lines in data.txt and prints only the unique line which is the password +exit and login to next level using ssh +**password : 4CKMh1JI91bUIZZPXDqGanal4xvAg0JM** + +### Level 9 to Level 10 +```bash +ls -alps +``` +> lists all the directory contents of bandit9 +```bash +cat data.txt +``` +> gives the contents of the file data.txt +```bash +ls +``` +```bash +file data +``` +> shows the type of the file data which is gzip + +```bash +strings data.txt +``` +> converts data in data.txt in strings +```bash +strings data.txt | grep === +``` +> prints strings succeeded by === in data.txt +exit and login to next level using ssh +**password : FGUW5ilLVJrxX9kMYMmlN4MgbpfMiqey** + +### Level 10 to Level 11 +```bash +ls -alps +``` +> lists all the directory contents of bandit10 +```bash +cat data.txt +``` +> gives the contents of the file data.txt +```bash +base64 -d data.txt +``` +> decodes the base64 encoded data in data.txt +exit and login to next level using ssh +**password : dtR173fZKb0RRsDFSGsg2RWnpNVj3qRr** + +### Level 11 to Level 12 +```bash +ls -alps +``` +> lists all the directory contents of bandit11 +```bash +cat data.txt +``` +> gives the contents of the file data.txt +```bash +cat data.txt | tr [a-zA-Z] [n-za-mN-ZA-M] +``` +> rotates every letter in data.txt by 13 places to give the password +exit and login to next level using ssh +**password : 7x16WNeHIi5YkIhWsfFIqoognUTyj9Q4** + +### Level 12 to Level 13 +```bash +ls +``` +> lists all the directory contents of bandit12 +```bash +cat data.txt +``` +> gives the contents of the file data.txt +mkdir /tmp/pssd (creates a new directory pssd under /tmp) +```bash +cp data.txt /tmp/pssd +``` +> copies contents of data.txt to /tmp/pssd +```bash +cd /tmp/pssd +``` +> changes working directory to /tmp/pssd +```bash +ls +``` +> lists all the directory contents of /tmp/pssd +```bash +xxd -r data.txt > data +``` +> creates a hexdump of data.txt to data +```bash +ls +``` +```bash +file data +``` +> Shows the type of file "data" is +```bash +mv data file.gz +``` +> renames data to file.gz +```bash +ls +``` +```bash +gzip -d file.gz +``` +> compresses gzip type file.gz +```bash +ls +``` +```bash +file file +``` +> Shows the type of "file" after compression +```bash +mv file file.bz2 +``` +> Renames file to file.bz2 +```bash +bzip2 -d file.bz2 +``` +> Compresses bzip2 type file.bz2 +```bash +ls +``` +```bash +file file +``` +> Shows the type of "file" after compression +```bash +mv file file.gz +``` +> renames data to file.gz +```bash +gzip -d file.gz +``` +> compresses gzip type file.gz +```bash +ls +``` +```bash +file file +``` +> Shows the type of "file" after compression +```bash +mv file file.tar +``` +> renames data to file.tar +```bash +tar xf file.tar +``` +> Creates a compressed archive of file.tar +```bash +ls +``` +```bash +rm file.tar +``` +> removes file.tar +```bash +rm data.txt +``` +> removes data.txt +```bash +ls +``` +```bash +file data5.bin +``` +> Shows the type of "data5.bin" +```bash +mv data5.bin data.tar +``` +> renames data5.bin to data.tar +```bash +tar xf data.tar +``` +> Creates a compressed archive of data.tar +```bash +ls +``` +```bash +file data6.bin +``` +> Shows the type of "data6.bin" +```bash +mv data6.bin data.bz2 +``` +> renames data6.bin to data.bz2 +```bash +bzip2 -d data.bz2 +``` +> Compresses bzip2 type data.bz2 +```bash +ls +``` +```bash +file data +``` +> Shows the type of "data" after compression +```bash +mv data data.tar +``` +> renames data to data.tar +```bash +ls +``` +```bash +tar xf data.tar +``` +> Creates a compressed archive of data.tar +```bash +ls +``` +```bash +file data8.bin +``` +> Shows the type of "data8.bin" +```bash +mv data8.bin data.gz +``` +> renames data8.bin to data.gz +```bash +gzip -d data.gz +``` +> compresses gzip type data.gz +```bash +ls +``` +```bash +file data +``` +> Shows the type of "data" after compression +```bash +cat data +``` +> gives the password stored in "data" +exit and login to next level using ssh +**password : FO5dwFsc0cbaIiH0h8J2eUks2vdTDwAn** + +### Level 13 to Level 14 +```bash +ls +``` +> lists all the directory contents of bandit13 +```bash +ssh -i sshkey.private bandit14@localhost -p 2220 (sshkey.private helps us login to the next level) +``` + +### Level 14 to Level 15 +```bash +cat /etc/bandit_pass/bandit14 +``` +> gives the password for the current level as specified in the previous level +**password for level 14: MU4VWeTyJk8ROof1qqmcBPaLh7lDCPvS** +```bash +nc localhost 30000 then enter password found above and this gives password for next level. +``` +**password for level 15: 8xCjnmgoKbGLhHFAZlGE5Tmu4M2tKJQo** + +THE END!!!!!!!!! \ No newline at end of file diff --git a/admin.cpp b/admin.cpp new file mode 100644 index 0000000..79527cc --- /dev/null +++ b/admin.cpp @@ -0,0 +1,80 @@ +#include "admin.h" +#include + +using namespace std; + +Admin::Admin(const string& uname, const string& pwd) + : username(uname), password(pwd) {} + +bool Admin::login(const string& uname, const string& pwd) const { + return uname == username && pwd == password; +} + +void Admin::addMovie(vector>& library) { + string title, genre; + double rating, rent_cost, purchase_cost; + int duration; + + cout << "Enter Movie Title: "; + cin.ignore(); + getline(cin, title); + cout << "Genre: "; + getline(cin, genre); + cout << "Rating (0.0 - 10.0): "; + cin >> rating; + cout << "Duration (minutes): "; + cin >> duration; + cout << "Rent Cost: ₹"; + cin >> rent_cost; + cout << "Purchase Cost: ₹"; + cin >> purchase_cost; + + library.push_back(make_shared(title, genre, rating, duration, rent_cost, purchase_cost)); + cout << "Movie added successfully.\n"; +} + +void Admin::addTVShow(vector>& library) { + string title, genre; + double rating, rent_cost, purchase_cost; + int seasons, episodes; + + cout << "Enter TV Show Title: "; + cin.ignore(); + getline(cin, title); + cout << "Genre: "; + getline(cin, genre); + cout << "Rating (0.0 - 10.0): "; + cin >> rating; + cout << "Number of Seasons: "; + cin >> seasons; + cout << "Episodes per Season: "; + cin >> episodes; + cout << "Rent Cost per Season: ₹"; + cin >> rent_cost; + cout << "Purchase Cost per Season: ₹"; + cin >> purchase_cost; + + library.push_back(make_shared(title, genre, rating, seasons, episodes, rent_cost, purchase_cost)); + cout << "TV Show added successfully.\n"; +} + +void Admin::removeContent(vector>& library, const string& title) { + for (auto it = library.begin(); it != library.end(); ++it) { + if ((*it)->getTitle() == title) { + library.erase(it); + cout << "Content \"" << title << "\" removed successfully.\n"; + return; + } + } + cout << "Content titled \"" << title << "\" not found.\n"; +} + +void Admin::checkUserCharges(const vector& users, const string& uname) const { + for (const auto& user : users) { + if (user.getUsername() == uname) { + cout << "User \"" << uname << "\" has ₹" << user.getChargesDue() << " due.\n"; + return; + } + } + cout << "User \"" << uname << "\" not found.\n"; +} diff --git a/admin.h b/admin.h new file mode 100644 index 0000000..0d218c7 --- /dev/null +++ b/admin.h @@ -0,0 +1,28 @@ +#ifndef ADMIN_H +#define ADMIN_H + +#include +#include +#include +#include "content.h" +#include "user.h" + +using namespace std; + +class Admin { +private: + string username; + string password; + +public: + Admin(const string& uname = "admin", const string& pwd = "admin123"); + + bool login(const string& uname, const string& pwd) const; + + void addMovie(vector>& library); + void addTVShow(vector>& library); + void removeContent(vector>& library, const string& title); + void checkUserCharges(const vector& users, const string& username) const; +}; + +#endif // ADMIN_H diff --git a/admin.o b/admin.o new file mode 100644 index 0000000..37c89bd Binary files /dev/null and b/admin.o differ diff --git a/content.cpp b/content.cpp new file mode 100644 index 0000000..c02034c --- /dev/null +++ b/content.cpp @@ -0,0 +1,40 @@ +#include "content.h" + +Content::Content(const std::string& t, const std::string& g, double r) + : title(t), genre(g), rating(r), is_rented(false), is_purchased(false) {} + +std::string Content::getTitle() const { return title; } +std::string Content::getGenre() const { return genre; } +double Content::getRating() const { return rating; } +bool Content::isRented() const { return is_rented; } +bool Content::isPurchased() const { return is_purchased; } + +void Content::markRented() { is_rented = true; } +void Content::markReturned() { is_rented = false; } +void Content::markPurchased() { is_purchased = true; } + +Movie::Movie(const std::string& t, const std::string& g, double r, int d, double rent, double purchase) + : Content(t, g, r), duration(d), rent_cost(rent), purchase_cost(purchase) {} + +void Movie::display() const { + std::cout << "[Movie] " << title << " | Genre: " << genre << " | Rating: " << rating + << " | Duration: " << duration << " min" + << " | Rent: ₹" << rent_cost << " | Buy: ₹" << purchase_cost << "\n"; +} + +std::string Movie::getType() const { return "Movie"; } +double Movie::getRentCost() const { return rent_cost; } +double Movie::getPurchaseCost() const { return purchase_cost; } + +TVShow::TVShow(const std::string& t, const std::string& g, double r, int s, int eps, double rent, double purchase) + : Content(t, g, r), seasons(s), episodes_per_season(eps), rent_cost_per_season(rent), purchase_cost_per_season(purchase) {} + +void TVShow::display() const { + std::cout << "[TV Show] " << title << " | Genre: " << genre << " | Rating: " << rating + << " | Seasons: " << seasons << " | Episodes/Season: " << episodes_per_season + << " | Rent/Season: ₹" << rent_cost_per_season << " | Buy/Season: ₹" << purchase_cost_per_season << "\n"; +} + +std::string TVShow::getType() const { return "TVShow"; } +double TVShow::getRentCostPerSeason() const { return rent_cost_per_season; } +double TVShow::getPurchaseCostPerSeason() const { return purchase_cost_per_season; } diff --git a/content.h b/content.h new file mode 100644 index 0000000..dee0a36 --- /dev/null +++ b/content.h @@ -0,0 +1,69 @@ +#ifndef CONTENT_H +#define CONTENT_H + +#include +#include + +using namespace std; + +class Content { +protected: + string title; + string genre; + double rating; + bool is_rented; + bool is_purchased; + +public: + Content(const string& t, const string& g, double r); + + virtual void display() const = 0; + virtual string getType() const = 0; + + string getTitle() const; + string getGenre() const; + double getRating() const; + bool isRented() const; + bool isPurchased() const; + + void markRented(); + void markReturned(); + void markPurchased(); + + virtual ~Content() = default; +}; + +class Movie : public Content { +private: + int duration; // in minutes + double rent_cost; + double purchase_cost; + +public: + Movie(const string& t, const string& g, double r, int d, double rent, double purchase); + + void display() const override; + string getType() const override; + + double getRentCost() const; + double getPurchaseCost() const; +}; + +class TVShow : public Content { +private: + int seasons; + int episodes_per_season; + double rent_cost_per_season; + double purchase_cost_per_season; + +public: + TVShow(const string& t, const string& g, double r, int s, int eps, double rent, double purchase); + + void display() const override; + string getType() const override; + + double getRentCostPerSeason() const; + double getPurchaseCostPerSeason() const; +}; + +#endif // CONTENT_H diff --git a/content.o b/content.o new file mode 100644 index 0000000..73fe07f Binary files /dev/null and b/content.o differ diff --git a/content.txt b/content.txt new file mode 100644 index 0000000..7523416 --- /dev/null +++ b/content.txt @@ -0,0 +1,40 @@ +Movie|Inception|Sci-Fi|8.8|50|200| +Movie|The Dark Knight|Action|9|45|180| +Movie|Interstellar|Sci-Fi|8.6|55|220| +Movie|Parasite|Thriller|8.6|40|170| +Movie|The Matrix|Sci-Fi|8.7|50|190| +Movie|Gladiator|Action|8.5|45|175| +Movie|Joker|Drama|8.4|40|160| +Movie|La La Land|Musical|8|35|150| +Movie|Titanic|Romance|7.9|50|200| +Movie|Shutter Island|Mystery|8.2|40|170| +Movie|The Godfather|Crime|9.2|55|230| +Movie|Avengers: Endgame|Superhero|8.4|60|250| +Movie|Forrest Gump|Drama|8.8|45|180| +Movie|Fight Club|Thriller|8.8|45|190| +Movie|The Prestige|Mystery|8.5|40|170| +Movie|Coco|Animation|8.4|35|140| +Movie|Whiplash|Drama|8.5|40|160| +Movie|Toy Story|Animation|8.3|30|120| +Movie|The Lion King|Animation|8.5|30|130| +Movie|The Social Network|Biography|7.7|35|150| +TVShow|Breaking Bad|Crime|9.5|100|400 +TVShow|Stranger Things|Sci-Fi|8.7|90|350 +TVShow|Game of Thrones|Fantasy|9.2|110|500 +TVShow|Friends|Comedy|8.9|70|300 +TVShow|The Office|Comedy|8.9|70|280 +TVShow|Sherlock|Mystery|9.1|90|360 +TVShow|Dark|Sci-Fi|8.8|85|320 +TVShow|Narcos|Crime|8.8|80|300 +TVShow|The Crown|Drama|8.6|85|320 +TVShow|Money Heist|Thriller|8.3|85|330 +TVShow|Peaky Blinders|Crime|8.8|90|340 +TVShow|The Mandalorian|Sci-Fi|8.7|90|320 +TVShow|Better Call Saul|Crime|8.9|100|380 +TVShow|The Witcher|Fantasy|8.2|85|310 +TVShow|Brooklyn Nine-Nine|Comedy|8.4|75|290 +TVShow|The Boys|Superhero|8.7|90|340 +TVShow|Lucifer|Fantasy|8.1|85|310 +TVShow|House of Cards|Drama|8.7|80|300 +TVShow|The 100|Sci-Fi|7.6|75|270 +TVShow|Rick and Morty|Animation|9.2|80|320 diff --git a/init_content.cpp b/init_content.cpp new file mode 100644 index 0000000..71d4edc --- /dev/null +++ b/init_content.cpp @@ -0,0 +1,51 @@ +#include "content.h" +#include +#include +#include "init_content.h" + +using namespace std; + +void initializeContent(vector>& content_library) { + + content_library.push_back(make_shared("Inception", "Sci-Fi", 8.8, 148, 50, 200)); + content_library.push_back(make_shared("The Dark Knight", "Action", 9.0, 152, 45, 180)); + content_library.push_back(make_shared("Interstellar", "Sci-Fi", 8.6, 169, 55, 220)); + content_library.push_back(make_shared("Parasite", "Thriller", 8.6, 132, 40, 170)); + content_library.push_back(make_shared("The Matrix", "Sci-Fi", 8.7, 136, 50, 190)); + content_library.push_back(make_shared("Gladiator", "Action", 8.5, 155, 45, 175)); + content_library.push_back(make_shared("Joker", "Drama", 8.4, 122, 40, 160)); + content_library.push_back(make_shared("La La Land", "Musical", 8.0, 128, 35, 150)); + content_library.push_back(make_shared("Titanic", "Romance", 7.9, 195, 50, 200)); + content_library.push_back(make_shared("Shutter Island", "Mystery", 8.2, 138, 40, 170)); + content_library.push_back(make_shared("The Godfather", "Crime", 9.2, 175, 55, 230)); + content_library.push_back(make_shared("Avengers: Endgame", "Superhero", 8.4, 181, 60, 250)); + content_library.push_back(make_shared("Forrest Gump", "Drama", 8.8, 142, 45, 180)); + content_library.push_back(make_shared("Fight Club", "Thriller", 8.8, 139, 45, 190)); + content_library.push_back(make_shared("The Prestige", "Mystery", 8.5, 130, 40, 170)); + content_library.push_back(make_shared("Coco", "Animation", 8.4, 105, 35, 140)); + content_library.push_back(make_shared("Whiplash", "Drama", 8.5, 107, 40, 160)); + content_library.push_back(make_shared("Toy Story", "Animation", 8.3, 81, 30, 120)); + content_library.push_back(make_shared("The Lion King", "Animation", 8.5, 88, 30, 130)); + content_library.push_back(make_shared("The Social Network", "Biography", 7.7, 120, 35, 150)); + + content_library.push_back(make_shared("Breaking Bad", "Crime", 9.5, 5, 13, 100, 400)); + content_library.push_back(make_shared("Stranger Things", "Sci-Fi", 8.7, 4, 9, 90, 350)); + content_library.push_back(make_shared("Game of Thrones", "Fantasy", 9.2, 8, 10, 110, 500)); + content_library.push_back(make_shared("Friends", "Comedy", 8.9, 10, 24, 70, 300)); + content_library.push_back(make_shared("The Office", "Comedy", 8.9, 9, 22, 70, 280)); + content_library.push_back(make_shared("Sherlock", "Mystery", 9.1, 4, 3, 90, 360)); + content_library.push_back(make_shared("Dark", "Sci-Fi", 8.8, 3, 8, 85, 320)); + content_library.push_back(make_shared("Narcos", "Crime", 8.8, 3, 10, 80, 300)); + content_library.push_back(make_shared("The Crown", "Drama", 8.6, 5, 10, 85, 320)); + content_library.push_back(make_shared("Money Heist", "Thriller", 8.3, 5, 10, 85, 330)); + content_library.push_back(make_shared("Peaky Blinders", "Crime", 8.8, 6, 6, 90, 340)); + content_library.push_back(make_shared("The Mandalorian", "Sci-Fi", 8.7, 3, 8, 90, 320)); + content_library.push_back(make_shared("Better Call Saul", "Crime", 8.9, 6, 10, 100, 380)); + content_library.push_back(make_shared("The Witcher", "Fantasy", 8.2, 3, 8, 85, 310)); + content_library.push_back(make_shared("Brooklyn Nine-Nine", "Comedy", 8.4, 8, 22, 75, 290)); + content_library.push_back(make_shared("The Boys", "Superhero", 8.7, 3, 8, 90, 340)); + content_library.push_back(make_shared("Lucifer", "Fantasy", 8.1, 6, 10, 85, 310)); + content_library.push_back(make_shared("House of Cards", "Drama", 8.7, 6, 13, 80, 300)); + content_library.push_back(make_shared("The 100", "Sci-Fi", 7.6, 7, 13, 75, 270)); + content_library.push_back(make_shared("Rick and Morty", "Animation", 9.2, 6, 10, 80, 320)); +} diff --git a/init_content.h b/init_content.h new file mode 100644 index 0000000..b79feb9 --- /dev/null +++ b/init_content.h @@ -0,0 +1,11 @@ +#ifndef INIT_CONTENT_H +#define INIT_CONTENT_H + +#include +#include +#include "content.h" +using namespace std; + +void initializeContent(vector> &contents); + +#endif // INIT_CONTENT_H diff --git a/init_content.o b/init_content.o new file mode 100644 index 0000000..d942e31 Binary files /dev/null and b/init_content.o differ diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..378bb6d --- /dev/null +++ b/main.cpp @@ -0,0 +1,215 @@ +#include +#include +#include +#include +#include "content.h" +#include "user.h" +#include "admin.h" +#include "persistence.h" +#include "init_content.h" + +using namespace std; + +vector users; +vector> content_library; +Admin admin; + +void userMenu(User& user); +void adminMenu(); + +User* findUser(const string& username) { + for (auto& u : users) { + if (u.getUsername() == username) + return &u; + } + return nullptr; +} + +void clearInput() { + cin.clear(); + cin.ignore(numeric_limits::max(), '\n'); +} + +void showContentByCategory(const string& type) { + cout << "Available " << type << "s:\n"; + for (const auto& c : content_library) { + if (c->getType() == type) { + c->display(); + cout << "------------------\n"; + } + } +} + +void searchContent() { + cout << "Search by:\n1. Title\n2. Genre\nChoice: "; + int choice; + cin >> choice; + clearInput(); + string query; + if (choice == 1) { + cout << "Enter title: "; + getline(cin, query); + for (const auto& c : content_library) + if (c->getTitle().find(query) != string::npos) + c->display(); + } else { + cout << "Enter genre: "; + getline(cin, query); + for (const auto& c : content_library) + if (c->getGenre().find(query) != string::npos) + c->display(); + } +} + +void userMenu(User& user) { + while (true) { + cout << "\nUser Menu:\n"; + cout << "1. Browse Movies\n2. Browse TV Shows\n3. Search Content\n"; + cout << "4. Rent Content\n5. Return Content\n6. Purchase Content\n"; + cout << "7. View Rented Items\n8. View Purchased Items\n"; + cout << "9. View Charges\n10. Pay Charges\n0. Logout\nChoice: "; + + int ch; + cin >> ch; + clearInput(); + + if (ch == 0) break; + + string title, rent_date = "2025-05-13", due_date = "2025-05-20"; + switch (ch) { + case 1: showContentByCategory("Movie"); break; + case 2: showContentByCategory("TVShow"); break; + case 3: searchContent(); break; + case 4: + cout << "Enter title to rent: "; + getline(cin, title); + for (auto& c : content_library) + if (c->getTitle() == title && !c->isRented()) { + user.rentContent(c, rent_date, due_date); + user.addCharge((c->getType() == "Movie") ? + dynamic_cast(c.get())->getRentCost() : + dynamic_cast(c.get())->getRentCostPerSeason()); + break; + } + break; + case 5: + cout << "Enter title to return: "; + getline(cin, title); + user.returnContent(title); + break; + case 6: + cout << "Enter title to purchase: "; + getline(cin, title); + for (auto& c : content_library) + if (c->getTitle() == title) { + user.purchaseContent(c); + user.addCharge((c->getType() == "Movie") ? + dynamic_cast(c.get())->getPurchaseCost() : + dynamic_cast(c.get())->getPurchaseCostPerSeason()); + break; + } + break; + case 7: user.viewRentedItems(); break; + case 8: user.viewPurchasedItems(); break; + case 9: cout << "Total charges due: ₹" << user.getChargesDue() << endl; break; + case 10: user.payCharges(); break; + default: cout << "Invalid option.\n"; + } + } +} + +void adminMenu() { + while (true) { + cout << "\nAdmin Menu:\n"; + cout << "1. Add Movie\n2. Add TV Show\n3. Remove Content\n"; + cout << "4. Check User Charges\n0. Logout\nChoice: "; + + int ch; + cin >> ch; + clearInput(); + + if (ch == 0) break; + + string title, uname; + switch (ch) { + case 1: admin.addMovie(content_library); break; + case 2: admin.addTVShow(content_library); break; + case 3: + cout << "Enter title to remove: "; + getline(cin, title); + admin.removeContent(content_library, title); + break; + case 4: + cout << "Enter username to check charges: "; + getline(cin, uname); + admin.checkUserCharges(users, uname); + break; + default: cout << "Invalid option.\n"; + } + } +} + +int main() { + users = Persistence::loadUsers(); + content_library = Persistence::loadContent(); + if (content_library.empty()) { + (content_library); + } + + while (true) { + cout << "\nWelcome to Netflix!\n"; + cout << "1. Sign Up\n2. Login\n3. Admin Login\n0. Exit\nChoice: "; + int ch; + cin >> ch; + clearInput(); + + if (ch == 0) break; + + string uname, pwd; + switch (ch) { + case 1: + cout << "Choose username: "; + getline(cin, uname); + if (findUser(uname)) { + cout << "Username already exists!\n"; + break; + } + cout << "Choose password: "; + getline(cin, pwd); + users.emplace_back(uname, pwd); + cout << "User registered successfully!\n"; + break; + + case 2: + cout << "Username: "; + getline(cin, uname); + cout << "Password: "; + getline(cin, pwd); + if (User* u = findUser(uname)) { + if (u->checkPassword(pwd)) { + cout << "Login successful!\n"; + userMenu(*u); + } else cout << "Wrong password.\n"; + } else cout << "User not found.\n"; + break; + + case 3: + cout << "Admin Username: "; + getline(cin, uname); + cout << "Admin Password: "; + getline(cin, pwd); + if (admin.login(uname, pwd)) { + cout << "Admin login successful!\n"; + adminMenu(); + } else cout << "Invalid admin credentials.\n"; + break; + + default: + cout << "Invalid option.\n"; + } + + Persistence::saveUsers(users); + Persistence::saveContent(content_library); + } + return 0; +} diff --git a/main.o b/main.o new file mode 100644 index 0000000..f20acd3 Binary files /dev/null and b/main.o differ diff --git a/persistence.cpp b/persistence.cpp new file mode 100644 index 0000000..dd20e2d --- /dev/null +++ b/persistence.cpp @@ -0,0 +1,77 @@ +#include "persistence.h" +#include +#include +#include + +using namespace std; + +void Persistence::saveUsers(const vector& users, const string& filename) { + ofstream out(filename); + for (const auto& user : users) { + out << user.serialize() << endl; + } + out.close(); +} + +vector Persistence::loadUsers(const string& filename) { + vector users; + ifstream in(filename); + string line; + while (getline(in, line)) { + if (!line.empty()) + users.push_back(User::deserialize(line)); + } + in.close(); + return users; +} + +void Persistence::saveContent(const vector>& content, const string& filename) { + ofstream out(filename); + for (const auto& item : content) { + if (item->getType() == "Movie") { + auto* m = dynamic_cast(item.get()); + out << "Movie|" << m->getTitle() << "|" << m->getGenre() << "|" << m->getRating() + << "|" << m->getRentCost() << "|" << m->getPurchaseCost() << "|" << endl; + } else if (item->getType() == "TVShow") { + auto* t = dynamic_cast(item.get()); + out << "TVShow|" << t->getTitle() << "|" << t->getGenre() << "|" << t->getRating() + << "|" << t->getRentCostPerSeason() << "|" << t->getPurchaseCostPerSeason() << endl; + } + } + out.close(); +} + +vector> Persistence::loadContent(const string& filename) { + vector> content; + ifstream in(filename); + string line; + + while (getline(in, line)) { + if (line.empty()) continue; + + stringstream ss(line); + string type, title, genre, temp; + double rating, rent, purchase; + + getline(ss, type, '|'); + getline(ss, title, '|'); + getline(ss, genre, '|'); + getline(ss, temp, '|'); + rating = stod(temp); + getline(ss, temp, '|'); + rent = stod(temp); + getline(ss, temp, '|'); + purchase = stod(temp); + + if (type == "Movie") { + int dummy_duration = 120; + content.push_back(make_shared(title, genre, rating, dummy_duration, rent, purchase)); + } else if (type == "TVShow") { + int dummy_seasons = 3, dummy_eps = 10; + content.push_back(make_shared(title, genre, rating, dummy_seasons, dummy_eps, rent, purchase)); + } + } + + in.close(); + return content; +} diff --git a/persistence.h b/persistence.h new file mode 100644 index 0000000..0b166bc --- /dev/null +++ b/persistence.h @@ -0,0 +1,21 @@ +#ifndef PERSISTENCE_H +#define PERSISTENCE_H + +#include +#include +#include +#include "user.h" +#include "content.h" + +using namespace std; + +class Persistence { +public: + static void saveUsers(const vector& users, const string& filename = "users.txt"); + static vector loadUsers(const string& filename = "users.txt"); + + static void saveContent(const vector>& content, const string& filename = "content.txt"); + static vector> loadContent(const string& filename = "content.txt"); +}; + +#endif // PERSISTENCE_H diff --git a/persistence.o b/persistence.o new file mode 100644 index 0000000..1f15ef7 Binary files /dev/null and b/persistence.o differ diff --git a/user.cpp b/user.cpp new file mode 100644 index 0000000..51cee0e --- /dev/null +++ b/user.cpp @@ -0,0 +1,98 @@ +#include "user.h" +#include +#include +#include + +using namespace std; + +User::User(const string& uname, const string& pwd) + : username(uname), password(pwd), charges_due(0.0) {} + +string User::getUsername() const { + return username; +} + +bool User::checkPassword(const string& pwd) const { + return pwd == password; +} + +void User::rentContent(shared_ptr content, const string& rent_date, const string& return_due_date) { + content->markRented(); + rented_items.push_back({content, rent_date, return_due_date}); + cout << "Rented \"" << content->getTitle() << "\" until " << return_due_date << "\n"; +} + +bool User::returnContent(const string& title) { + for (auto it = rented_items.begin(); it != rented_items.end(); ++it) { + if (it->content->getTitle() == title) { + it->content->markReturned(); + rented_items.erase(it); + cout << "Returned \"" << title << "\" successfully.\n"; + return true; + } + } + cout << "No rented item found with title: " << title << "\n"; + return false; +} + +void User::purchaseContent(shared_ptr content) { + content->markPurchased(); + purchased_items.push_back(content); + cout << "Purchased \"" << content->getTitle() << "\" successfully.\n"; +} + +void User::viewRentedItems() const { + if (rented_items.empty()) { + cout << "No items currently rented.\n"; + return; + } + cout << "Rented Items:\n"; + for (const auto& item : rented_items) { + cout << "- " << item.content->getTitle() + << " | Rented On: " << item.rent_date + << " | Return By: " << item.return_due_date << "\n"; + } +} + +void User::viewPurchasedItems() const { + if (purchased_items.empty()) { + cout << "No items purchased.\n"; + return; + } + cout << "Purchased Items:\n"; + for (const auto& item : purchased_items) { + cout << "- " << item->getTitle() << "\n"; + } +} + +double User::getChargesDue() const { + return charges_due; +} + +void User::addCharge(double amount) { + charges_due += amount; +} + +void User::payCharges() { + cout << "Paid ₹" << charges_due << " successfully.\n"; + charges_due = 0.0; +} + +string User::serialize() const { + ostringstream oss; + oss << username << "|" << password << "|" << charges_due; + return oss.str(); +} + +User User::deserialize(const string& line) { + istringstream iss(line); + string uname, pwd; + double charges; + getline(iss, uname, '|'); + getline(iss, pwd, '|'); + iss >> charges; + + User user(uname, pwd); + user.addCharge(charges); + return user; +} diff --git a/user.h b/user.h new file mode 100644 index 0000000..85a8a6e --- /dev/null +++ b/user.h @@ -0,0 +1,49 @@ +#ifndef USER_H +#define USER_H + +#include +#include +#include +#include +#include "content.h" + +using namespace std; + +struct RentalInfo { + shared_ptr content; + string rent_date; + string return_due_date; +}; + +class User { +private: + string username; + string password; + vector rented_items; + vector> purchased_items; + double charges_due; + +public: + User(const string& uname, const string& pwd); + + string getUsername() const; + bool checkPassword(const string& pwd) const; + + // Core functionalities + void rentContent(shared_ptr content, const string& rent_date, const string& return_due_date); + bool returnContent(const string& title); + void purchaseContent(shared_ptr content); + + void viewRentedItems() const; + void viewPurchasedItems() const; + + double getChargesDue() const; + void addCharge(double amount); + void payCharges(); + + // Persistence support + string serialize() const; + static User deserialize(const string& line); +}; + +#endif // USER_H diff --git a/user.o b/user.o new file mode 100644 index 0000000..0ccfaa0 Binary files /dev/null and b/user.o differ diff --git a/users.txt b/users.txt new file mode 100644 index 0000000..61d683f --- /dev/null +++ b/users.txt @@ -0,0 +1 @@ +paveets|123456|0