Advertisement
desislava_shunina

zad 2

Mar 25th, 2024
552
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 13.66 KB | None | 0 0
  1. #include <fstream>
  2. #include <iomanip>
  3. #include <iostream>
  4.  
  5. #pragma warning(disable : 4996)
  6. using std::cout;
  7.  
  8. namespace GlobalConstants
  9. {
  10. const uint16_t MAX_SONGNAME_LENGTH = 64;
  11. const uint16_t MAX_SONG_CONTENT_LENGTH_BYTES = 256;
  12. const uint16_t MAX_SONGS_IN_PLAYLIST = 30;
  13. const uint16_t MINUTES_IN_HOUR = 60;
  14. const uint16_t SECONDS_IN_MINUTE = 60;
  15. const uint16_t BUFFER_SIZE = 100;
  16. const uint16_t BITS_IN_BYTE = 8;
  17. } // namespace GlobalConstants
  18. namespace HelpingFunctions
  19. {
  20. char myToLower(char ch)
  21. {
  22.     if (!(ch >= 'A' && ch <= 'Z'))
  23.         return ch;
  24.  
  25.     return ch - ('A' - 'a');
  26. }
  27.  
  28. int myMin(int a, int b)
  29. {
  30.     return a < b ? a : b;
  31. }
  32.  
  33. int32_t bytesInFile(std::ifstream &ifs)
  34. {
  35.     if (!ifs.is_open())
  36.         return -1;
  37.  
  38.     int32_t curPos = ifs.tellg();
  39.     ifs.seekg(0, std::ios::end);
  40.  
  41.     int32_t endIndex = ifs.tellg();
  42.  
  43.     ifs.seekg(curPos);
  44.  
  45.     return endIndex;
  46. }
  47.  
  48. int32_t bytesInFile(const char *fileName)
  49. {
  50.     if (!fileName)
  51.         return -2; // error code
  52.  
  53.     std::ifstream ifs(fileName, std::ios::binary);
  54.     if (!ifs.is_open())
  55.         return -1; // error code
  56.  
  57.     int res = bytesInFile(ifs);
  58.     ifs.close();
  59.  
  60.     return res;
  61. }
  62.  
  63. void setBit(char &ch, uint16_t position) // indexing from 0...7
  64. {
  65.     if (position > 7)
  66.         return;
  67.     ch |= (1 << (GlobalConstants::BITS_IN_BYTE - position - 1)); // starting from left to right
  68. }
  69.  
  70. void printBits(char ch)
  71. {
  72.     for (int16_t i = (GlobalConstants::BITS_IN_BYTE - 1); i >= 0; i--)
  73.     {
  74.         cout << (bool)(ch & (1 << i));
  75.     }
  76. }
  77.  
  78. void copyCharArr(char *dest, const char *source, size_t length)
  79. {
  80.     if (!source || !dest)
  81.         return;
  82.     for (size_t i = 0; i < length; i++)
  83.     {
  84.         dest[i] = source[i];
  85.     }
  86. }
  87.  
  88. } // namespace HelpingFunctions
  89. namespace GenreInterface
  90. {
  91. enum class Genre : unsigned char
  92. {
  93.     ROCK = 1 << 0,
  94.     POP = 1 << 1,
  95.     HIP_HOP = 1 << 2,
  96.     ELECTRO = 1 << 3,
  97.     JAZZ = 1 << 4,
  98.     UNKNOWN = 0
  99. };
  100. const char *getStringRepresentation(Genre genre)
  101. {
  102.     char buff[GlobalConstants::BUFFER_SIZE] = {};
  103.     if (!(int)genre)
  104.     {
  105.         strcat(buff, "&Unknown");
  106.     }
  107.     else
  108.     {
  109.         if ((int)genre & (int)Genre::ROCK)
  110.             strcat(buff, "&Rock");
  111.         if ((int)genre & (int)Genre::POP)
  112.             strcat(buff, "&Pop");
  113.         if ((int)genre & (int)Genre::HIP_HOP)
  114.             strcat(buff, "&Hip-Hop");
  115.         if ((int)genre & (int)Genre::ELECTRO)
  116.             strcat(buff, "&Electronic");
  117.         if ((int)genre & (int)Genre::JAZZ)
  118.             strcat(buff, "&Jazz");
  119.     }
  120.  
  121.     char *res = new char[strlen(buff)]; // without the first & symbol
  122.  
  123.     strcpy(res, &buff[1]);
  124.  
  125.     return res;
  126. }
  127. Genre getGenreFromChar(char ch)
  128. {
  129.  
  130.     switch (HelpingFunctions::myToLower(ch))
  131.     {
  132.     case 'r':
  133.         return Genre::ROCK;
  134.     case 'p':
  135.         return Genre::POP;
  136.     case 'h':
  137.         return Genre::HIP_HOP;
  138.     case 'e':
  139.         return Genre::ELECTRO;
  140.     case 'j':
  141.         return Genre::JAZZ;
  142.     default:
  143.         return Genre::UNKNOWN;
  144.     }
  145. }
  146. } // namespace GenreInterface
  147.  
  148. using namespace GlobalConstants;
  149. using namespace GenreInterface;
  150. using namespace HelpingFunctions;
  151.  
  152. typedef char byte;
  153.  
  154. class Time
  155. {
  156.   private:
  157.     uint32_t seconds = 0;
  158.  
  159.     uint32_t getTotalMinutes() const
  160.     {
  161.         return seconds / SECONDS_IN_MINUTE;
  162.     }
  163.     uint32_t getTotalSeconds() const
  164.     {
  165.         return seconds;
  166.     }
  167.  
  168.   public:
  169.     Time()
  170.     {
  171.         seconds = 0;
  172.     }
  173.     Time(uint32_t hours, uint16_t minutes, uint16_t seconds)
  174.     {
  175.         this->setHours(hours);
  176.         this->setMinutes(minutes);
  177.         this->setSeconds(seconds);
  178.     }
  179.  
  180.     void setSeconds(uint16_t _seconds)
  181.     {
  182.         seconds = seconds - this->getSeconds() + _seconds;
  183.     }
  184.     void setMinutes(uint16_t minutes)
  185.     {
  186.         seconds = seconds - this->getMinutes() * SECONDS_IN_MINUTE + minutes * SECONDS_IN_MINUTE;
  187.     }
  188.     void setHours(uint32_t hours)
  189.     {
  190.         seconds = seconds - this->getHours() * MINUTES_IN_HOUR * SECONDS_IN_MINUTE +
  191.                   hours * MINUTES_IN_HOUR * SECONDS_IN_MINUTE;
  192.     }
  193.  
  194.     uint16_t getMinutes() const
  195.     {
  196.         return this->getTotalMinutes() % MINUTES_IN_HOUR;
  197.     }
  198.     uint16_t getSeconds() const
  199.     {
  200.         return seconds % SECONDS_IN_MINUTE;
  201.     }
  202.     uint32_t getHours() const
  203.     {
  204.         return this->getTotalMinutes() / MINUTES_IN_HOUR;
  205.     }
  206.  
  207.     void print() const
  208.     {
  209.         uint32_t hours_ = this->getHours();
  210.         uint16_t minutes_ = this->getMinutes(), seconds_ = this->getSeconds();
  211.  
  212.         // printing with leading zeros if needed
  213.         cout << std::setw(2) << std::setfill('0') << hours_ << ':' << std::setw(2) << std::setfill('0') << minutes_
  214.              << ':' << std::setw(2) << std::setfill('0') << getSeconds();
  215.     }
  216. };
  217.  
  218. class Melody
  219. {
  220.   private:
  221.     byte content[MAX_SONG_CONTENT_LENGTH_BYTES] = {};
  222.     uint16_t length = 0; // in bytes
  223.     bool isGood = true;
  224.  
  225.   public:
  226.     Melody()
  227.     {
  228.         length = 0;
  229.         isGood = this->setContent("", 0);
  230.     }
  231.     Melody(const byte *_content, uint16_t _length)
  232.     {
  233.         isGood = this->setContent(_content, _length);
  234.     }
  235.  
  236.     const byte *getContent() const
  237.     {
  238.         return content;
  239.     }
  240.     uint16_t getLength() const
  241.     {
  242.         return length;
  243.     }
  244.     bool isOK() const
  245.     {
  246.         return isGood;
  247.     }
  248.  
  249.     bool setContent(const byte *_content, uint16_t _length)
  250.     {
  251.         if (_length > MAX_SONG_CONTENT_LENGTH_BYTES || !content)
  252.             return false;
  253.  
  254.         copyCharArr(content, _content, _length);
  255.         length = _length;
  256.         return true;
  257.     }
  258.  
  259.     void changeRhythm(uint16_t tactInterval)
  260.     {
  261.         if (tactInterval == 0) // we want a positive step
  262.             return;
  263.  
  264.         uint16_t curBit = tactInterval - 1; // counting is from 0
  265.         while (curBit < MAX_SONG_CONTENT_LENGTH_BYTES * BITS_IN_BYTE)
  266.         {
  267.             setBit(content[curBit / BITS_IN_BYTE], curBit % BITS_IN_BYTE);
  268.             curBit += tactInterval;
  269.         }
  270.     }
  271.     void print() const
  272.     {
  273.         for (uint16_t i = 0; i < length; i++)
  274.         {
  275.             printBits(content[i]);
  276.         }
  277.     }
  278. };
  279.  
  280. class Song
  281. {
  282.   private:
  283.     char name[MAX_SONGNAME_LENGTH] = {};
  284.     Time duration;
  285.     Genre genre = Genre::UNKNOWN;
  286.     Melody melody;
  287.     bool isGood = true;
  288.  
  289.   public:
  290.     Song()
  291.     {
  292.     }
  293.     Song(const char *_name, const Time &_duration, Genre _genre, const Melody _melody)
  294.     {
  295.         if (!name)
  296.         {
  297.             isGood = false;
  298.             return;
  299.         }
  300.  
  301.         strcpy(name, _name);
  302.         duration = _duration;
  303.         genre = _genre;
  304.         melody = _melody;
  305.     }
  306.  
  307.     const char *getName() const
  308.     {
  309.         return name;
  310.     }
  311.     const Time &getDuration() const
  312.     {
  313.         return duration;
  314.     }
  315.     const Genre &getGenre() const
  316.     {
  317.         return genre;
  318.     }
  319.     const Melody &getMelody() const
  320.     {
  321.         return melody;
  322.     }
  323.     bool isOK() const
  324.     {
  325.         return isGood;
  326.     }
  327.  
  328.     void setName(const char *str)
  329.     {
  330.         if (!str)
  331.         {
  332.             isGood = false;
  333.             return;
  334.         }
  335.         strcpy(name, str);
  336.     }
  337.     void setDuration(uint32_t hours, uint16_t minutes, uint16_t seconds)
  338.     {
  339.         duration.setHours(hours);
  340.         duration.setMinutes(minutes);
  341.         duration.setSeconds(seconds);
  342.     }
  343.     void setGenre(Genre _genre)
  344.     {
  345.         genre = _genre;
  346.     }
  347.     void setMelody(Melody _melody)
  348.     {
  349.         melody = _melody;
  350.     }
  351.  
  352.     void changeRhythm(uint16_t tactInterval)
  353.     {
  354.         melody.changeRhythm(tactInterval);
  355.     }
  356.     void save(const char *destName) const
  357.     {
  358.         if (!destName)
  359.             return;
  360.  
  361.         std::ofstream ofs(destName, std::ios::binary);
  362.         if (!ofs.is_open())
  363.             return;
  364.         ofs.write(this->getMelody().getContent(), sizeof(byte) * this->getMelody().getLength());
  365.         ofs.close();
  366.     }
  367.  
  368.     void print() const
  369.     {
  370.         cout << name << ", ";
  371.         duration.print();
  372.         const char *temp_str = getStringRepresentation(genre);
  373.         cout << ", " << temp_str;
  374.         delete[] temp_str;
  375.     }
  376. };
  377.  
  378. class Playlist
  379. {
  380.   private:
  381.     uint16_t songsCount = 0;
  382.     Song songs[MAX_SONGS_IN_PLAYLIST];
  383.     // uint16_t songsCount[]; // we could fill the padding to save memory
  384.  
  385.   public:
  386.     uint16_t getSongsCount() const
  387.     {
  388.         return songsCount;
  389.     }
  390.     const Song *getSongs() const
  391.     {
  392.         return songs;
  393.     }
  394.  
  395.     bool add(const char *songName, unsigned hours, unsigned minutes, unsigned seconds, const char *genre,
  396.              const char *sourceFile)
  397.     {
  398.         if (songsCount >= MAX_SONGS_IN_PLAYLIST)
  399.             return false;
  400.  
  401.         if (!songName || !sourceFile || !genre)
  402.             return false;
  403.  
  404.         std::ifstream ifs(sourceFile, std::ios::binary);
  405.  
  406.         if (!ifs.is_open())
  407.             return false;
  408.  
  409.         songs[songsCount].setName(songName);                    // init name
  410.         songs[songsCount].setDuration(hours, minutes, seconds); // init duration
  411.  
  412.         byte buff[MAX_SONG_CONTENT_LENGTH_BYTES];
  413.         ifs.read(buff, sizeof(buff)); // read content
  414.         ifs.clear();
  415.         uint16_t newMelodyLength = bytesInFile(ifs);
  416.         ifs.close();
  417.         if (newMelodyLength >= MAX_SONG_CONTENT_LENGTH_BYTES || newMelodyLength == -1)
  418.             return false;
  419.         Melody newMelody(buff, newMelodyLength);
  420.         songs[songsCount].setMelody(newMelody); // init melody
  421.  
  422.         Genre newGenre = Genre::UNKNOWN;
  423.         while (*genre) // init genre
  424.             newGenre = (Genre)((unsigned char)newGenre |
  425.                                (unsigned char)getGenreFromChar(*(genre++))); // get all Genre configuration
  426.  
  427.         songs[songsCount].setGenre(newGenre);
  428.  
  429.         songsCount++;
  430.         return true;
  431.     }
  432.     void print() const
  433.     {
  434.         for (uint16_t i = 0; i < songsCount; i++)
  435.         {
  436.             songs[i].print();
  437.             cout << std::endl;
  438.         }
  439.     }
  440.     int16_t find(const char *name) const
  441.     {
  442.         if (!name)
  443.             return -2;
  444.         for (uint16_t i = 0; i < songsCount; i++)
  445.         {
  446.             if (strcmp(name, songs[i].getName()) == 0)
  447.             {
  448.                 // songs[i].print();
  449.                 return i;
  450.             }
  451.         }
  452.         return -1; // not found
  453.     }
  454.     void findGenre(char ch) const
  455.     {
  456.         for (uint16_t i = 0; i < songsCount; i++)
  457.         {
  458.             if ((unsigned char)songs[i].getGenre() & (unsigned char)getGenreFromChar(ch)) // if they have common Genres
  459.             {
  460.                 songs[i].print();
  461.                 cout << std::endl;
  462.             }
  463.         }
  464.     }
  465.     void selectionSortByComparator(bool (*isLess)(const Song &, const Song &))
  466.     {
  467.  
  468.         for (uint16_t i = 0; i < songsCount - 1; i++)
  469.         {
  470.             uint16_t minElIndex = i;
  471.             for (uint16_t j = i + 1; j < songsCount; j++)
  472.             {
  473.                 if (isLess(songs[j], songs[minElIndex]))
  474.                 {
  475.                     minElIndex = j;
  476.                 }
  477.             }
  478.             if (minElIndex != i)
  479.                 std::swap(songs[i], songs[minElIndex]);
  480.         }
  481.     }
  482.     void sortByName()
  483.     {
  484.         selectionSortByComparator(
  485.             [](const Song &first, const Song &second) { return strcmp(first.getName(), second.getName()) < 0; });
  486.     }
  487.     void sortByDuration()
  488.     {
  489.         selectionSortByComparator([](const Song &first, const Song &second) {
  490.             return first.getDuration().getSeconds() < second.getDuration().getSeconds();
  491.         });
  492.     }
  493.     void save(const char *songName, const char *destName) const
  494.     {
  495.         if (!songName || !destName)
  496.             return;
  497.  
  498.         int16_t songIndex = this->find(songName);
  499.         if (songIndex == -1)
  500.             return; // not found
  501.  
  502.         std::ofstream ofs(destName, std::ios::binary);
  503.         if (!ofs.is_open())
  504.             return;
  505.  
  506.         ofs.write(songs[songIndex].getMelody().getContent(), sizeof(byte) * songs[songIndex].getMelody().getLength());
  507.         ofs.close();
  508.     }
  509.     void mix(const char *song1Name, const char *song2Name)
  510.     {
  511.         if (!song1Name || !song2Name)
  512.             return;
  513.  
  514.         uint16_t song1Index = this->find(song1Name);
  515.         uint16_t song2Index = this->find(song2Name);
  516.         if (song1Index == -1 || song2Index == -1)
  517.             return; // song not found
  518.         uint16_t minLengthOfMelody =
  519.             myMin(songs[song1Index].getMelody().getLength(), songs[song2Index].getMelody().getLength());
  520.  
  521.         byte newContent[BUFFER_SIZE];
  522.         for (uint16_t i = 0; i < minLengthOfMelody; i++)
  523.         {
  524.             newContent[i] =
  525.                 songs[song1Index].getMelody().getContent()[i] ^ songs[song2Index].getMelody().getContent()[i];
  526.         }
  527.         Melody newMelody(newContent, songs[song1Index].getMelody().getLength());
  528.         songs[song1Index].setMelody(newMelody);
  529.     }
  530. };
  531.  
  532. int main()
  533. {
  534.     // Playlist p;
  535.     // p.add("Song 2", 0, 1, 55, "rp", "song2.txt");
  536.     // p.add("Song 1", 0, 1, 5, "p", "song1.txt");
  537.     //  p.add("A1", 0, 1, 5, "p", "song1.txt");
  538.  
  539.     // p.print();
  540.     //  p.getSongs()[p.find("Song 1")].print();
  541.     // p.findGenre('p');
  542.     // p.findGenre('r');
  543.     // p.sortByName();
  544.     // p.sortByDuration();
  545.     // p.print();
  546.     // p.save("Song 2", "test.txt");
  547.     // p.mix("Song 1", "Song 2");
  548.  
  549.     // p.save("Song 1", "test2.txt");
  550.     // Song my = p.getSongs()[p.find("Song 2")];
  551.     // Melody m("\0\0", 2);
  552.     // my.setMelody(m);
  553.     // my.changeRhythm(3);
  554.     // my.getMelody().print();
  555. }
  556.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement