Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

HW: Temperature Queries (Part 1) Points Points 10 Design 75 Working Program 15 C

ID: 3918461 • Letter: H

Question

HW: Temperature Queries (Part 1)

Points

Points

10

Design

75

Working Program

15

Code Review

100

TOTAL

Submission

Design: Submit the PDF to eCampus.

Source Code: Submit the source code (LinkedList.h, LinkedList.cpp, Node.h, TemperatureData.h, TemperatureData.cpp, TemperatureDatabase.h, TemperatureDatabase.cpp, and main.cpp files) to Mimir

To compile on the VM replace the makefile with the following:
Click to download makefile.

Specifications

Part 1: You will implement a linked list to organize temperature sensor readings from a file.

Part 2: Process a file with queries to report based on the data.

Design

Algorithm for inserting new nodes into the correct location.

Algorithm for determining if one set of data (i.e. location, date) is less than another set of data.

Additional Components: Test cases

Program

You will implement a program that receives as input two files:

A temperature file (e.g., temps.dat)
This file contains historic average temperatures for several locations in Texas. The data has been obtained from the United States Historical Climate Network (USCHN). Each line of the file contains a location, a date, and the average temperature (in Celsius) for that location and date. A string, corresponding to a meteorological station id, represents a location. For example, “411048” (string not number) corresponds to Brenham, Texas. A date is specified by two integers: a year and a month. A sample line in the temperature file would be:

410120 1893 2 6.41

The temperature value -99.99 is used by the UCHN agency to represent missing information, for example:

410120 1893 1 -99.99

Valid temperatures are assumed to be in the interval -50.0 to 50.0 (remember that they use Celsius, so this is a good range). The first valid year is 1800. The latest valid year should be our current year. You can declare a constant in your program to specify the current year. (If we were programming this to be used for real, we would instead obtain the current year from the system, so that no code changes are required for future years.)

temps.dat might look like this:
411048 2015 1 9.58
411048 2015 3 14.82
411048 2016 4 20.51
411048 2016 1 10.99
411000 1973 1 0.54
411048 2016 3 18.40
411048 2016 5 -99.99

A query file (e.g., queries.dat)
Details will be given with part 2.

Requirements

You must use this skeleton code to create your program.

Your implementation has to use a linked list to store the data you read from the temperature file.

You must implement a function named “getHead()” in the class LinkedList. This function is supposed to return the pointer to the start Node of the list.

You must implement an overloaded operator< for struct Node and you must use this operator to to compare Nodes while inserting into the LinkedList. The nodes in the linked list are:

First ordered by location

Then by date (i.e. by year and then by month)

Your program should receive the names of the input files as command line arguments. The first argument will be the temperature file, the second the queries file. We’ll use the queries file next week.

If the input files contain a line with an invalid format, you should output on the console an error message and finish executing the program.

Do not throw an exception.

Output the message in the console beginning “Error: “ followed by the description shown below followed by the invalid value. For example:

Error: Invalid temperature -1221.11

Error: Invalid year 2020

Error: Invalid month 0

Error: Unable to open input.dat

Error: Other invalid input

Examples of lines with invalid format for temps.dat:
4111000 1889 0 -4.3
4111000 1889 18 -4.3
4111000 2016 01 -1222.11
4111000 1889 .8 8.3
4111000 2015 11

You are required to use classes and comply with the “Rule of 3” (see zyBook and slides). More specifically, you need to implement the constructor, destructor, copy assignment, and copy constructor for the LinkedList class and any other class that uses the heap/freestore, but I don’t think any other class should use the heap.

The constructor for your Node and TemperatureData classes should take all data items (station id, year, month, average temperature value) as parameters. Use initialization in the “membername(value)” format (see zyBook and slides)

We’ll test these directly.

Implement the print() function for the linked list. Use this function and/or the overloaded output operator to test your results. We’ll test the linked list functions directly for part 1. The expectation is that the list will be printed out in the correct order based on the comparison rules listed earlier.

Grading

We will unit test the LinkedList class, including insert, print, constructors and rule of 3, and overloaded output operator (which is already done for you if you get print to work.

We will unit test Node and TemperatureData classes.

We will unit test TemperatureDatabase loadData() function. We will look for error messages.

Sample Input/Output Files

Building the list input files

Zip file

temp-3lines.dat, temp-7lines.dat, etc.

Hints & Comments

Write a myTest() function for the TemperatureDatabase. You can call that function from main after loading the Database to test thinks like the rule of three, print(), etc.

Use the print() function to print out your linked list so that you can make sure that you are maintaining it in order as required. First test with the small sample input files that we provide (e.g., first the one with 3 lines, then the one with 7 lines of data.), output your linked list, and inspect it to see if it is representing the input data correctly.

It is often a good idea to develop your solution incrementally, completing and testing components of your overall program as you develop them.

Points

10

Design

75

Working Program

15

Code Review

100

TOTAL

HEAD 411048820151| 9.5841104882015|3 14.82 4110488 2016 420.51 TAIL

Explanation / Answer

As per your question i had written a programme below.

File: node.h

#ifndef NODE
#define NODE

#include <iostream>
#include <string>
using namespace std;

struct Node
{
   // Pointer to the next node in the linkedlist
   int location;
   int year;
   int month;
   double temperature;
   string query;
   int queryType;
   Node* next;

    // Default constructor
   Node() : next(nullptr)
   {
       location = 0;
       year = 0;
       month = 0;
       temperature = 0.0;
       queryType = 0;
   }

   // Arguments constructor
   Node(int loc, int yr, int mn, double temper) :next(nullptr)
   {
       location = loc;
       year = yr;
       month = mn;
       temperature = temper;
       queryType = 0;
   }

   // The function below is written. Do notmodify it
   virtual ~Node() {}
};
#endif

File: linkedlist.h

#ifndef LINKEDLIST
#define LINKEDLIST

#include "node.h"

class LinkedList
{
private:
   Node* head;
   Node* tail;

public:
   // Default constructor
   LinkedList();

   // Destructor
   ~LinkedList();

   // Copy constructor
   LinkedList(const LinkedList& other);

   // Assignment constructor
   LinkedList& operator=(const LinkedList&other);

   // Insert a record to the linked list
   void insert(int location, int year, int month,double temperature);  

   // Clear the content of this linkedlist
   void clear();
  
   friend std::ostream&operator<<(std::ostream&, const LinkedList&);

   Node* getHead();
   void insertOrder(int loc, int sYear, int eYear,int type, double value);
   bool isValidateData(int loc, int sYear, inteYear);

   // The functions below are written already.Do not modify them.
   void print() const;
   void print(std::ostream&) const;
};

std::ostream& operator<<(std::ostream& os, constLinkedList& ll);
#endif


File: linkedlist.cpp

#include "linkedlist.h"
#include <sstream>

LinkedList::LinkedList()
{
   head = nullptr;
   tail = nullptr;
}

LinkedList::~LinkedList()
{
   clear();
}

LinkedList::LinkedList(const LinkedList& source)
{
   Node* previous = source.head;
   this->head = nullptr;

   if (previous != nullptr)
   {
       Node* node = new Node;
       node->location =previous->location;
       node->year =previous->year;
       node->month =previous->month;
       node->temperature =previous->temperature;
       node->query =previous->query;
       node->next =previous->next;
       this->head = node;
       Node* current =this->head;
       previous =previous->next;

       while (previous !=nullptr)
       {
           node = newNode;
           node->location = previous->location;
           node->year = previous->year;
           node->month = previous->month;
           node->temperature = previous->temperature;
           node->query = previous->query;
           node->next = previous->next;
           current->next = node;
           current =current->next;
           previous =previous->next;
       }
   }
}

LinkedList& LinkedList::operator=(const LinkedList&source)
{
   clear();
   Node* previous = source.head;
   if (previous != nullptr)
   {
       Node* node = new Node;
       node->location =previous->location;
       node->year =previous->year;
       node->month =previous->month;
       node->temperature =previous->temperature;
       node->query =previous->query;
       node->next =previous->next;
       this->head = node;
       Node* current =this->head;
       previous =previous->next;
       while (previous !=nullptr)
       {
           node = newNode;
           node->location = previous->location;
           node->year = previous->year;
           node->month = previous->month;
           node->temperature = previous->temperature;
           node->query = previous->query;
           node->next = previous->next;
           current->next = node;
           current =current->next;
           previous =previous->next;
       }
   }

   return *this;
}

void LinkedList::insert(int location, int year, int month,double temperature)
{
   Node* node = new Node(location, year, month,temperature);  
   Node* current = head;
   Node* previous = nullptr;

   if (this->head == nullptr &&this->tail == nullptr)
   {
       head = node;
       tail = node;
       return;
   }

   if (node->location <current->location)
   {
       node->next =current;
       head = node;
   }

   while (node->location >current->location)
   {
       if (current->next ==nullptr)
       {
           current->next = node;
           node->next = nullptr;
           return;
       }

       previous = current;
       current =current->next;
   }

   if (node->location ==current->location)
   {
       while (node->year >current->year)
       {
           if(current->next == nullptr)
           {
              current->next = node;
              node->next = nullptr;
              return;
           }

           previous = current;
           current =current->next;
       }

       if (node->year ==current->year)
       {
           while(node->month > current->month)
           {
              if (current->next == nullptr)
              {
                  current->next =node;
                  node->next =nullptr;
                  return;
              }

              previous = current;
              current = current->next;
           }

           if(node->month == current->month)
           {
              while (node->temperature >current->temperature)
              {
                  if (current->next ==nullptr)
                  {
                      current->next = node;
                      node->next = nullptr;
                      return;
                  }

                  previous =current;
                  current =current->next;
              }
           }
           else
           {
              previous->next = node;
              node->next = current;
           }
       }
       else
       {
           previous->next = node;
           node->next = current;
       }
   }
   else
   {
       previous->next =node;
       node->next =current;
   }
}


void LinkedList::clear()
{
   Node* current = this->head;
   while (current != nullptr)
   {
       Node* previous =current;
       current =current->next;
       delete previous;
   }
}

void LinkedList::print() const
{
   print(cout);
}

void LinkedList::print(ostream& os) const
{
   os << *this;
}

ostream& operator<<(ostream& os, constLinkedList& ll)
{
   Node *current = ll.head;

   while ( current != 0)
   {
       if (current->queryType !=0)
       {
           os<< current->location << ' ' <<current->year << ' ' << current->month << '';

           if(current->queryType == 1)
              os << "AVG" << ' ';

           if(current->queryType == 2)
              os << "MODE" << ' ';

           os<< current->query << endl;
       }
       else
       {
           os<< current->location << ' ' <<current->year << ' ' << current->month << '' << current->temperature << endl;
       }

       current =current->next;
   }

   return os;
}

Node* LinkedList::getHead()
{
   return this->head;
}

void LinkedList::insertOrder(int loc, int sYear, int eYear, inttype, double value)
{
   Node* node = new Node(loc, sYear, eYear,value);
   node->queryType = type;

   if (value == -999)
   {
       node->query ="unknown";
   }
   else
   {
       ostringstream oss;
       oss << value;
       node->query =oss.str();
   }

   if (this->head == nullptr &&this->tail == nullptr)
   {
       this->head = node;
       this->tail = node;
   }
   else
   {
       Node* current = head;
       while (current->next !=nullptr)
       {
           current =current->next;
       }

       current->next =node;
   }
}

bool LinkedList::isValidateData(int loc, int sYear, inteYear)
{
   Node* current = head;

   while (current->location != loc &&current != nullptr)
   {
       current =current->next;
   }

   while (current->location == loc &&current->year > sYear && current != nullptr)
   {
       current =current->next;
   }

   if (current->location == loc &&current->year >= sYear && current->year <=eYear)
   {
       return true;
   }

   return false;
}

File: temperaturedb.h

#ifndef TEMPERATURE_DB
#define TEMPERATURE_DB

#include "linkedlist.h"

class TemperatureDatabase
{
public:
   TemperatureDatabase() {}
   ~TemperatureDatabase() {}   
  
   void loadData(const std::string&data_file);
   void performQuery(const std::string&query_filename);

   void findMode(int location, int sYear, inteYear);
   void findAVG(int location, int sYear, inteYear);
   double findRoundValue(double value);

private:
   LinkedList records;
   LinkedList queries;  
};

#endif


File: temperaturedb.cpp

#include "temperaturedb.h"
#include <fstream>
#include <vector>

void TemperatureDatabase::loadData(const std::string&data_file)
{
   ifstream infile(data_file);
   if (!infile.is_open())
   {
       cout << "Input filecould not be opened!" << endl;
       return;
   }
  
   int currentYear = 2018;
   int n = 0;

   while (!infile.eof())
   {
       int location, year,month;
       double value;

       try
       {         
           infile>> location >> year >> month >>value;
           if(location > 99999 && location < 1000000)
           {
              if (year > 1799 && year <currentYear)
              {
                  if (month > 0&& month < 13)
                  {
                      if(value > -51 && value < 51)
                      {
                         records.insert(location, year, month,value);
                         n++;
                      }
                      else
                      {
                         throw runtime_error("Error: Invaliddata.");
                      }
                  }
                  else
                  {
                      throw runtime_error("Error: Invalid month.");
                  }
              }
              else
              {
                  throwruntime_error("Error: Invalid year.");
              }
           }
           else
           {
              throw runtime_error("Error: Invalidlocation.");
           }
       }
       catch (construntime_error& re)
       {
           cout<< re.what() << endl;
       }
   }

   infile.close();
}

void TemperatureDatabase::performQuery(const std::string&query_filename)
{
   ifstream infile(query_filename);
   if (!infile.is_open())
   {
       cout << "Input filecould not be opened!" << endl;
       return;
   }
  
   while (!infile.eof())
   {
       int location, sYear,eYear;
       string query;
      
       try
       {         
           infile>> location >> query >> sYear >> eYear;

           if(!(location > 99999 && location < 999999))
           {
              throw runtime_error("Error: Invalidlocation.");
           }

           if(!(sYear > 1799 && sYear < 2018) || !(eYear > 1799&& eYear < 2019) || (eYear < sYear))
           {
              throw runtime_error("Error: Invalidyear.");
           }

           boolvalidData = records.isValidateData(location, sYear, eYear);

           if(!validData)
           {
              if (query == "AVG")
              {
                  queries.insertOrder(location, sYear, eYear, 1, -999);
              }
              else if (query == "MODE")
              {
                  queries.insertOrder(location, sYear, eYear, 2, -999);
              }
              else
              {
                  throwruntime_error("Error: Invalid query.");
              }
           }

           if((query == "AVG" || query == "MODE") && validData)
           {
              if (query == "AVG")
                  findAVG(location,sYear, eYear);

              if (query == "MODE")
                  findMode(location,sYear, eYear);
           }
       }
       catch (construntime_error& re)
       {
           cout<< re.what() << endl;
       }
   }
   infile.close();

   ofstream outfile("results.dat");
   if (!outfile.is_open())
       cout << "Output filecould not be opened!" << endl;
   else
       outfile <<this->queries;
}


void TemperatureDatabase::findAVG(int location, int sYear, inteYear)
{
   Node* current = records.getHead();
   double total = 0.0;
   double average = 0.0;
   int n = 0;

   while (current->location < location&& current != nullptr)
   {
       current =current->next;
   }

   while (current->location == location&& current->year >= sYear && current->year<= eYear)
   {
       total +=current->temperature;
       current =current->next;
       n++;
   }
      
   if (n != 0)
   {
       average = total / n;
       queries.insertOrder(location,sYear, eYear, 1, average);
   }
}

void TemperatureDatabase::findMode(int location, int sYear, inteYear)
{  
   Node* current = records.getHead();
   vector<int> positives(51, 0);
   vector<int> negatives(50, 0);
   int temp = 0;
   int mode = 0;

   while (current->location != location&& current != nullptr)
   {
       current =current->next;
   }

   while (current->location == location&& current->year >= sYear && current->year<= eYear)
   {
       double value =current->temperature;

       if (value >= 0)
       {
           value =findRoundValue(value);
           positives.at((int)value) += 1;
       }
       else
       {
           value =findRoundValue(value);
           negatives.at(-1 * (int)value - 1) += 1;
       }
       current =current->next;
   }

   for (unsigned int i = 0; i <positives.size(); i++)
   {
       if (positives.at(i) >temp)
       {
           mode =i;
           temp =positives.at(i);
       }
   }

   for (unsigned int i = 0; i <negatives.size(); i++)
   {
       if (negatives.at(i) >temp)
       {
           mode = -1* i - 1;
           temp =negatives.at(i);
       }
   }

   queries.insertOrder(location, sYear, eYear,2, mode);
}

double TemperatureDatabase::findRoundValue(double value)
{
   double currentVal = value;
   if (value >= 0)
   {
       if ((currentVal -floor(value)) >= 0.5)
           returnceil(value);
       else
           returnfloor(value);
   }
   else
   {
       if(-(currentVal)-(floor(value)) >= 0.5)
           returnceil(value);
       else
           returnfloor(value);
   }
}

// File: main.cpp

#include "temperaturedb.h"

int main(int argc, char** argv)
{
   if (argc < 3)
   {
       cout << "Validcommandline arguments are not found." << endl;
       return 1;
   }

   TemperatureDatabase db;
   db.loadData(argv[1]);
   db.performQuery(argv[2]);
   return 0;
}

Please Hit Like if you find this answer helpful.