diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..2a586d60038879687dd20f90977af0b719d20703
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2021 Ivanov, Ivan (UG - Computer Science)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..ff05f2fd8bd902ff1bbb64d5c0bdc1468492873f
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,6 @@
+build:
+	go get
+run:
+	go run . $(file)
+test:
+	go test
\ No newline at end of file
diff --git a/README.md b/README.md
index 391b083923e35535161a0d7536e2ad3745912970..72096c98737a2e374d28cf138eff2f3a5fbf24d6 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,14 @@
-# json-utility
+# JSON Utility
+## Usage
+```
+$ make build
+$ make run file=example.json #where example.json is the file we want to process
+```
 
+## Testing
+```
+$ make test
+```
+
+## Dependencies
+- You'd need to have GOPATH exported.  GOBIN for MACOS for go get command
\ No newline at end of file
diff --git a/handler.go b/handler.go
new file mode 100644
index 0000000000000000000000000000000000000000..b7a9b9bd8d4f7aee4ee94b328b0e937b278eb54d
--- /dev/null
+++ b/handler.go
@@ -0,0 +1,58 @@
+package main
+
+import (
+	"encoding/json"
+	"log"
+	"os"
+	"sync"
+)
+
+//Handles opens the JSON file and calls extractJSON to parse
+//the data. Returns the result as a struct.
+func Handles(argument string) (urls *URLs, err error) {
+	jsonFile, err := os.Open(argument)
+	if err != nil {
+		log.Println(err)
+		return nil, err
+	}
+	log.Println("Successfully Opened", argument)
+	//Close when done.
+	defer jsonFile.Close()
+	result := ExctractJSON(jsonFile)
+	return result, err
+}
+
+func PrintResult(result *URLs) {
+	for k, v := range result.URL {
+		log.Println("For URL: ", k)
+		for m, x := range v.Date {
+			log.Println("↳", m, "there are:", x.Counter, "unique visits.")
+		}
+	}
+}
+
+func ExctractJSON(file *os.File) (urls *URLs) {
+	d := json.NewDecoder(file)
+
+	var loads []Load
+	visited := URLs{URL: make(map[string]*Dates)}
+
+	err := d.Decode(&loads)
+	if err != nil {
+		log.Panic(err)
+		return
+	}
+	wg := new(sync.WaitGroup)
+
+	for _, load := range loads {
+		if load.TypeRequest != "GET" {
+			log.Println("Request is invalid: ", load.TypeRequest)
+			continue
+		}
+		wg.Add(1)
+		go Process(&visited, load, wg)
+
+	}
+	wg.Wait()
+	return &visited
+}
diff --git a/handlertest.go b/handlertest.go
new file mode 100644
index 0000000000000000000000000000000000000000..69bd69cd781496426c5af0f3f47c0a044a675934
--- /dev/null
+++ b/handlertest.go
@@ -0,0 +1,74 @@
+package main
+
+import (
+	"fmt"
+	"log"
+	"testing"
+)
+
+/*
+Standard assert Equals function
+*/
+func assertEqual(t *testing.T, a interface{}, b interface{}, message string) {
+	if a == b {
+		return
+	}
+	if len(message) == 0 {
+		message = fmt.Sprintf("%v != %v", a, b)
+	}
+	t.Fatal(message)
+}
+
+/*
+Testing with sample JSON tha websites are visited.
+*/
+func TestWebsites(t *testing.T) {
+	result, err := Handles("test/test-websites.json")
+	if err != nil {
+		log.Println(err)
+		return
+	}
+
+	assertEqual(t, len(result.URL), 1, "")
+}
+
+/*
+Testing if a user visits one URL multiple times but in
+different days if it's still going to add it.
+*/
+func TestWebsites2(t *testing.T) {
+	result, err := Handles("test/test-websites2.json")
+	if err != nil {
+		log.Println(err)
+		return
+	}
+	assertEqual(t, len(result.URL), 1, "")
+}
+
+/*
+Testing if each date gets added. Basic case. 1 user visits 1 page on
+2 different dates. 2 Dates should be returned. Also checks if POST
+requests get dropped.
+*/
+func TestDates(t *testing.T) {
+	result, err := Handles("test/test-dates.json")
+	if err != nil {
+		log.Println(err)
+		return
+	}
+	assertEqual(t, len(result.URL["http://www.someamazingwebsite.com/1"].Date), 2, "")
+}
+
+/*
+Testing if each date gets added. Advaced case. 3 user visits 2 page on
+3 different dates. 2 Dates should be returned for each website.
+*/
+func TestDates2(t *testing.T) {
+	result, err := Handles("test/test-dates2.json")
+	if err != nil {
+		log.Println(err)
+		return
+	}
+	assertEqual(t, len(result.URL["http://www.someamazingwebsite.com/1"].Date), 2, "")
+	assertEqual(t, len(result.URL["http://www.someamazingwebsite.com/2"].Date), 2, "")
+}
diff --git a/json-utility b/json-utility
new file mode 100755
index 0000000000000000000000000000000000000000..7016e122e48334e254edbffd295222cb94d05229
Binary files /dev/null and b/json-utility differ
diff --git a/main.go b/main.go
index de079339eb73be6df7f869159b5228254759b755..c336ddadf774bab85e26f61cfed4acf3291105e0 100644
--- a/main.go
+++ b/main.go
@@ -1,10 +1,5 @@
-/*
-Example payload:
-userid: A unique ID representing the user
-url : The URL the visitor has accessed
-type: The HTTP method used to access the URL
-timestamp: The timestamp for when the action occurred
-*/
+// Package implments JSON parser utility to process a stream of JSON messages
+// and calculate the number of unique viewers per day for each URL in the stream.
 package main
 
 import (
@@ -15,23 +10,23 @@ import (
 
 type Load struct {
 	Userid      string `json:"userid"`
-	Url         string `json:"url"`
+	URL         string `json:"url"`
 	TypeRequest string `json:"type"`
 	Timestamp   int64  `json:"timestamp"`
 }
 
 type URLs struct {
-	URL map[string]*Dates
-	mux sync.RWMutex
+	URL map[string]*Dates //map holding all the Dates a certain URL is visited
+	mux sync.RWMutex      //mutex for race condition
 }
 type Dates struct {
-	Exists map[string]*Visits
+	Date map[string]*Visits //map holding all visits for certain date
 }
 
 type Visits struct {
-	mux     sync.RWMutex
-	Counter int
-	UserIds map[string]bool
+	mux     sync.RWMutex    //mutex for race condition
+	Counter int             //Counter for unique visits
+	UserIds map[string]bool //map holding different user ids
 }
 
 func main() {
@@ -40,27 +35,12 @@ func main() {
 		log.Println("USAGE: ./json-utility [path/to/file]")
 		return
 	}
-	openFile(os.Args[1])
-}
-
-func openFile(argument string) {
-	jsonFile, err := os.Open(argument)
+	//Get the result from a file.
+	result, err := Handles(os.Args[1])
 	if err != nil {
 		log.Println(err)
 		return
 	}
-	log.Println("Successfully Opened", argument)
-	//Close when done.
-	defer jsonFile.Close()
-	result := handler(jsonFile)
-
-	for k, v := range result.URL {
-
-		log.Println("For URL: ", k)
-
-		for m, x := range v.Exists {
-			log.Println("↳", m, "there are:", x.Counter, "unique visits.")
-		}
-
-	}
+	//Print the result
+	PrintResult(result)
 }
diff --git a/process.go b/process.go
new file mode 100644
index 0000000000000000000000000000000000000000..13ab0545c95e994dd47ce61d74589402c6c1ed10
--- /dev/null
+++ b/process.go
@@ -0,0 +1,73 @@
+package main
+
+import (
+	"log"
+	"sync"
+	"time"
+)
+
+//Process handles processing a load given by
+func Process(visited *URLs, load Load, wg *sync.WaitGroup) {
+	//Notify main that this routine is done.
+	defer wg.Done()
+	//Time should be accepted both in epoch milliseconds or seconds.
+	var t string
+	if time.Now().UnixNano() > load.Timestamp {
+		t = time.Unix(load.Timestamp/1000, 0).Format("2006-01-02")
+	} else {
+		t = time.Unix(load.Timestamp, 0).Format("2006-01-02")
+	}
+
+	visited.mux.Lock()
+
+	if date, ok := visited.URL[load.URL]; ok {
+		log.Println("URL exists.")
+		if visit, ok := date.Date[t]; ok {
+			log.Println("Date exists.")
+			if visit.UserIds[load.Userid] {
+				visited.mux.Unlock()
+				return //Return as the user has already visited that website for this day once.
+			} else {
+
+				visit.mux.Lock()
+				visit.Counter += 1
+				visit.UserIds[load.Userid] = true
+
+				visited.mux.Unlock()
+				visit.mux.Unlock()
+				return
+			}
+		} else {
+			//Add the Date and a Visit.
+			entry := Visits{Counter: 0, UserIds: make(map[string]bool)}
+			entry.mux.Lock()
+			entry.Counter += 1
+			entry.UserIds[load.Userid] = true
+			entry.mux.Unlock()
+
+			visited.URL[load.URL].Date[t] = &entry
+			visited.mux.Unlock()
+
+			log.Println("Date and Visit are added.")
+			return
+		}
+	} else {
+		log.Println("URL doesn't exist.")
+		//Initialising URL, date and visits for that date.
+
+		entry := Visits{Counter: 0, UserIds: make(map[string]bool)}
+		entry.mux.Lock()
+
+		dates := Dates{Date: make(map[string]*Visits)}
+
+		entry.Counter += 1
+		entry.UserIds[load.Userid] = true
+		entry.mux.Unlock()
+
+		dates.Date[t] = &entry
+
+		visited.URL[load.URL] = &dates
+		visited.mux.Unlock()
+		return
+	}
+}
diff --git a/test/test-dates.json b/test/test-dates.json
new file mode 100644
index 0000000000000000000000000000000000000000..28c515146fae92b8b942e052705e013b05d8c9bb
--- /dev/null
+++ b/test/test-dates.json
@@ -0,0 +1,14 @@
+[
+    {
+        "userid": "user1",
+        "url": "http://www.someamazingwebsite.com/1",
+        "type": "GET",
+        "timestamp": 1360662163000
+    },
+    {
+        "userid": "user2",
+        "url": "http://www.someamazingwebsite.com/1",
+        "type": "GET",
+        "timestamp": 1160165163000
+    }
+]
\ No newline at end of file
diff --git a/test/test-dates2.json b/test/test-dates2.json
new file mode 100644
index 0000000000000000000000000000000000000000..5da1d9ae8425699ab0361253bd274b447df6c78f
--- /dev/null
+++ b/test/test-dates2.json
@@ -0,0 +1,38 @@
+[
+    {
+        "userid": "user1",
+        "url": "http://www.someamazingwebsite.com/1",
+        "type": "GET",
+        "timestamp": 1360662163000
+    },
+    {
+        "userid": "user2",
+        "url": "http://www.someamazingwebsite.com/3",
+        "type": "GET",
+        "timestamp": 1160165163000
+    },
+    {
+        "userid": "user3",
+        "url": "http://www.someamazingwebsite.com/1",
+        "type": "GET",
+        "timestamp": 1358122163000
+    },
+    {
+        "userid": "user1",
+        "url": "http://www.someamazingwebsite.com/2",
+        "type": "GET",
+        "timestamp": 1360662163000
+    },
+    {
+        "userid": "user2",
+        "url": "http://www.someamazingwebsite.com/2",
+        "type": "GET",
+        "timestamp": 1160165163000
+    },
+    {
+        "userid": "user3",
+        "url": "http://www.someamazingwebsite.com/2",
+        "type": "GET",
+        "timestamp": 1358122163000
+    }
+]
\ No newline at end of file
diff --git a/test/test-websites.json b/test/test-websites.json
new file mode 100644
index 0000000000000000000000000000000000000000..8a309917ca5683922e50cf7b4e2e2cc1f44678cc
--- /dev/null
+++ b/test/test-websites.json
@@ -0,0 +1,14 @@
+[
+    {
+        "userid": "user1",
+        "url": "http://www.someamazingwebsite.com/1",
+        "type": "POST",
+        "timestamp": 1360662163000
+    },
+    {
+        "userid": "user2",
+        "url": "http://www.someamazingwebsite.com/1",
+        "type": "GET",
+        "timestamp": 1360662163000
+    }
+]
\ No newline at end of file
diff --git a/test/test-websites2.json b/test/test-websites2.json
new file mode 100644
index 0000000000000000000000000000000000000000..7b115afa06147f4213136aec7db9ec250e71694e
--- /dev/null
+++ b/test/test-websites2.json
@@ -0,0 +1,21 @@
+[
+    {
+        "userid": "user2",
+        "url": "http://www.someamazingwebsite.com/1",
+        "type": "GET",
+        "timestamp": 1360662163000
+    },
+    {
+        "userid": "user2",
+        "url": "http://www.someamazingwebsite.com/1",
+        "type": "GET",
+        "timestamp": 1360662163000
+    },
+    {
+        "userid": "user2",
+        "url": "http://www.someamazingwebsite.com/1",
+        "type": "GET",
+        "timestamp": 1310666163000
+    }
+
+]
\ No newline at end of file