diff --git a/srp_analysis/Cargo.toml b/srp_analysis/Cargo.toml
index cb6789f8378ce6ff6973d02aa0a38583a1d70d14..ab13076b89fc3b06deab41f67f1bd49297f6afec 100644
--- a/srp_analysis/Cargo.toml
+++ b/srp_analysis/Cargo.toml
@@ -7,3 +7,6 @@ edition = "2018"
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
 [dependencies]
+serde = { version = "1.0", features = ["derive"] }
+structopt = { version = "0.3"}
+serde_json = "1.0"
diff --git a/srp_analysis/src/analysis.rs b/srp_analysis/src/analysis.rs
index e91754a8413bc04d98d960e97ee32afe44da400b..9c1a634bbeb8a733ae77edc3c2f670eb70651e1e 100644
--- a/srp_analysis/src/analysis.rs
+++ b/srp_analysis/src/analysis.rs
@@ -18,7 +18,7 @@ pub fn analysis(tasks: &Tasks, exact: bool) -> Vec<TaskData>{
 
 // Checks if the analysis is schedulable
 // returns false if it is not schedulable
-pub fn schedulable_check(analysis: Vec<TaskData>) -> bool{
+pub fn schedulable_check(analysis: &Vec<TaskData>) -> bool{
     // check if response time is less then deadline
     for a in analysis {
         if a.task.deadline < a.response_time {
diff --git a/srp_analysis/src/common.rs b/srp_analysis/src/common.rs
index 40db8b72dbfb4074ac88565f7751564994bc734c..7be93ce187e44bbfbd07734008181bd407c50ea1 100644
--- a/srp_analysis/src/common.rs
+++ b/srp_analysis/src/common.rs
@@ -1,6 +1,7 @@
 use std::collections::{HashMap, HashSet};
+use serde::{Deserialize, Serialize};
 
-#[derive(Debug, Clone)]
+#[derive(Debug, Clone, Serialize, Deserialize)]
 pub struct TaskData {
     pub task: Task,
     pub response_time: u32,
@@ -9,7 +10,7 @@ pub struct TaskData {
     pub preemption_time: u32 
 }
 
-#[derive(Debug, Clone)]
+#[derive(Debug, Clone, Serialize, Deserialize)]
 pub struct Task {
     pub id: String,
     pub prio: u8,
@@ -18,8 +19,7 @@ pub struct Task {
     pub trace: Trace,
 }
 
-//#[derive(Debug, Clone)]
-#[derive(Debug, Clone)]
+#[derive(Debug, Clone, Serialize, Deserialize)]
 pub struct Trace {
     pub id: String,
     pub start: u32,
diff --git a/srp_analysis/src/main.rs b/srp_analysis/src/main.rs
index 302baeb7e2f5dd05d7b3945e0a4ecad209572865..fbbf6f62c7cc7efe06b3b5a68759993a1aba1d5e 100644
--- a/srp_analysis/src/main.rs
+++ b/srp_analysis/src/main.rs
@@ -2,29 +2,138 @@ mod common;
 mod analysis;
 use analysis::*;
 use common::*;
+use structopt::StructOpt;
+use std::path::PathBuf;
 
-fn main() {
+use std::fs::File;
+use std::io::prelude::*;
 
-    let tasks = taskset_2();
+#[derive(Debug, StructOpt)]
+#[structopt(name = "srp analysis", about = "Example:
+    cargo run -- -e         
+    cargo run -- -e -o analysis_1.json
+    cargo run -- -e -i tasks_1.json
+    cargo run -- -e -i tasks_2.json -o analysis_2.json")]
+struct Opt {
+    #[structopt(short, long)]
+    exact: bool,
+
+    #[structopt(short, long)]
+    output_analysis: Option<PathBuf>,
+
+    #[structopt(short, long)]
+    input_tasks: Option<PathBuf>,
+
+}
+
+fn main() -> std::io::Result<()> {
+
+    let opt = Opt::from_args();
+    // println!("{:?}", opt);
+
+    /* SAVES DOWN THE TASKS SET 1 and 2 to json
+    let tasks_1 = &taskset_1();
+    let tasks_2 = &taskset_2();
+    let tasks_1_json: String = serde_json::to_string(&tasks_1).unwrap();
+    let tasks_2_json: String = serde_json::to_string(&tasks_2).unwrap();
+    write_file_string(tasks_1_json, "tasks_1.json".to_string());
+    write_file_string(tasks_2_json, "tasks_2.json".to_string());
+    */
+    
+    // Default task set
+    let mut tasks: Tasks = taskset_1();
+
+    // Tasks input, if no input a default task input taskset_1 is used
+    match opt.input_tasks {
+        Some(file) => {
+            let mut file = File::open(file)?;
+            let mut contents = String::new();
+            file.read_to_string(&mut contents)?;
+            tasks = serde_json::from_str(&contents).unwrap();
+            println!("\nTask set is loaded from {:?}", file);
+        }
+        None => println!("\nA default task set is loaded!")
+    };
+
+    // Print out tasks
+    println!("---------------------------- Tasks ----------------------------\n");
+    for t in &tasks {
+        println!("Task {} | Prio {} | Deadline {} | Inter_arrival {} |", 
+                t.id, t.prio, t.deadline, t.inter_arrival);
+        println!("{:?} \n", t.trace);
+    }
+    println!("----------------------------------------------------------------\n");
 
     // let (ip, tr) = pre_analysis(&tasks);
     // println!("{:?}", ip);
     // println!("{:?}", tr);
 
-    println!("CPU load {}", load_factor(&tasks));
-    let analysis = analysis(&tasks, true);
+    // Calculate and print load factor for the CPU
+    let load_f = load_factor(&tasks);
+    println!("\nCPU load: {}\n", load_f);
+
+    // Prints out if exact or apporoximated preemptions calculation
+    if opt.exact {
+        println!("Exact preemption calculation: YES\n");
+    } else {
+        println!("Exact preemption calculation: NO\n");
+    }
+
+    // Makes the analysis
+    let analysis = analysis(&tasks, opt.exact);
+
+    // Prints out the results of the analysis
+    println!("---------------------------- Results of the analysis ----------------------------\n");
     for a in &analysis {
-        println!("{:?} Response time {} | WCET {} | Blocking time {} | Preemption time {}", 
+        println!("Task {:?} | Response time {} | WCET {} | Blocking time {} | Preemption time {} |\n", 
                 a.task.id, a.response_time, a.wcet, a.blocking_time, a.preemption_time);
     }
-    if schedulable_check(analysis) {
-        println!("OK! The taskset is schedulable!")
+    println!("---------------------------------------------------------------------------------\n");
+
+    // Checks if the analysis is schedulable and prints out the results
+    let schedule_check = schedulable_check(&analysis);
+    if schedule_check && !(load_f > 1.0) {
+        println!("The taskset is schedulable: YES\n")
     } else {
-        println!("ERROR! The taskset is NOT schedulable!")
+        println!("The taskset is schedulable: NO\n");
+        println!("Reasons:");
+        if load_f > 1.0 {
+            println!("- The CPU is overloaded!\n");
+        }
+        if schedule_check {
+            println!("- Deadline miss!\n")
+        }
     }
+
+    // Output analysis saved as json?
+    let analysis_json: String = serde_json::to_string(&analysis).unwrap();
+    match opt.output_analysis {
+        Some(file) => {
+            match write_file(analysis_json, file) {
+                Ok(()) => (),
+                Err(err) => panic!(err), 
+            }
+            println!("The Analysis is saved: YES\n");
+        }
+        None => println!("The Analysis is saved: NO\n"),
+    };
+    Ok(())
+
     
 }
 
+fn write_file_string(contents: String, file_name: String) -> std::io::Result<()> {
+    let mut file = File::create(file_name)?;
+    file.write_all(contents.as_bytes())?;
+    Ok(())
+}
+
+fn write_file(contents: String, file_name: PathBuf) -> std::io::Result<()> {
+    let mut file = File::create(file_name)?;
+    file.write_all(contents.as_bytes())?;
+    Ok(())
+}
+
 fn taskset_1() -> Tasks {
     let t1 = Task {
         id: "T1".to_string(),