diff --git a/.gitignore b/.gitignore
index 667aaef..9212cbc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -31,3 +31,7 @@ build/
### VS Code ###
.vscode/
+.DS_Store
+stockscope/src/main/java/com/.DS_Store
+stockscope/.DS_Store
+stockscope/.DS_Store
diff --git a/ArchitecturalDesign/ArchitecturalCompliance.md b/ArchitecturalDesign/ArchitecturalCompliance.md
new file mode 100644
index 0000000..77a7d20
--- /dev/null
+++ b/ArchitecturalDesign/ArchitecturalCompliance.md
@@ -0,0 +1,19 @@
+# Architecture Compliance
+
+## Overview
+The system has been designed using a layered structure based on Clean Architecture principles. This approach was chosen to keep the application organised and to make it easier to maintain and extend as new features are added in later stages of development.
+
+## Layered Structure
+The architecture is divided into four main layers: presentation, application, domain, and infrastructure. The presentation layer is responsible for handling user interaction through the Web UI and passing requests to the controller. The application layer manages the main flow of the system, including retrieving share price data, processing it, and preparing it for comparison. The domain layer represents the core concepts of the system and remains independent from technical concerns. The infrastructure layer handles external operations such as accessing market data and storing cached data locally.
+
+## Dependency Direction
+The system follows the principle that dependencies should flow inward. This means that outer layers depend on inner layers, but inner layers do not depend on outer layers. As a result, the core logic of the system remains independent from frameworks, APIs, and storage mechanisms. This makes the design more stable, as changes in external components do not directly affect the core of the application.
+
+## Use of Interfaces
+Interfaces are used to separate the application logic from the infrastructure layer. The application layer defines the required behaviour through interfaces, while the infrastructure layer provides the concrete implementations. For example, data retrieval and caching are handled through interfaces, allowing different implementations to be used without changing the main logic of the system.
+
+## Separation of Concerns
+The design ensures that responsibilities are clearly separated. Business logic is contained within the service layer and is not mixed with API calls or database operations. This helps to avoid tightly coupled code and makes the system easier to understand and maintain.
+
+## Summary
+Overall, the system follows Clean Architecture principles by organising components into clear layers, controlling the direction of dependencies, and using interfaces to reduce coupling. This results in a design that is flexible, maintainable, and suitable for future development.
diff --git a/ArchitecturalDesign/BusinessConceptModel.md b/ArchitecturalDesign/BusinessConceptModel.md
new file mode 100644
index 0000000..bea2c27
--- /dev/null
+++ b/ArchitecturalDesign/BusinessConceptModel.md
@@ -0,0 +1,26 @@
+# Business Concept Model
+
+## Overview
+This diagram shows the main ideas behind the share price comparison app and how they connect. It focuses on what the system does from a user point of view rather than how it is built.
+
+## Business Concept Model Diagram
+
+
+## Main Concepts
+The centre of the model is the Comparison. This represents the main task in the system where a user compares share prices over time.
+
+A User can create multiple comparisons which shows that users can analyse different shares whenever they want.
+
+Each comparison uses a Date Range. This defines the time period for the data being viewed.
+
+The comparison is carried out on one or two Shares. Each share belongs to a Company which represents the business that owns the stock.
+
+Each share has a Price History which stores all price data over time. This is made up of multiple Price Records where each record represents the price on a specific day.
+
+The results are shown using a Chart which displays the comparison in a clear visual way.
+
+## Relationships
+The diagram shows how these concepts are linked. A user requests a comparison, a comparison uses a date range and compares shares, and each share is connected to its company and price data. The chart then displays the final result.
+
+## Summary
+This model gives a clear view of the key concepts in the system and how they relate to each other. It helps explain the problem before moving on to the technical design in later stages.
diff --git a/ArchitecturalDesign/BusinessTypeModel.md b/ArchitecturalDesign/BusinessTypeModel.md
new file mode 100644
index 0000000..d8c8f51
--- /dev/null
+++ b/ArchitecturalDesign/BusinessTypeModel.md
@@ -0,0 +1,9 @@
+# Business Type Model
+
+
+
+### Notes
+- Derived from previous models/diagrams
+- Aligned with Java code
+- Date ranges must not exceed two years
+- Focussed only on domain types, core design only
diff --git a/ArchitecturalDesign/README.md b/ArchitecturalDesign/ComponentSpecificationDiagram.md
similarity index 98%
rename from ArchitecturalDesign/README.md
rename to ArchitecturalDesign/ComponentSpecificationDiagram.md
index 3a0c6fb..4bc545f 100644
--- a/ArchitecturalDesign/README.md
+++ b/ArchitecturalDesign/ComponentSpecificationDiagram.md
@@ -7,6 +7,7 @@
+
## Architectural Concepts and Their Application
diff --git a/ArchitecturalDesign/DependencyStructure.md b/ArchitecturalDesign/DependencyStructure.md
new file mode 100644
index 0000000..0733a13
--- /dev/null
+++ b/ArchitecturalDesign/DependencyStructure.md
@@ -0,0 +1,19 @@
+# Review of Dependency Structure
+
+## Overview
+The dependency structure of the system was reviewed to ensure that components are organised correctly and that dependencies follow a clear and logical direction. The aim was to confirm that the system avoids tight coupling and supports a maintainable design.
+
+## Dependency Relationships
+The system does not contain any circular dependencies between classes or packages. Each component depends only on what is necessary, and the overall flow of control is clear. The user interacts with the UI, which passes requests to the controller. The controller then calls the service layer, and the service layer interacts with external functionality through defined interfaces. This creates a clear and predictable flow through the system.
+
+## Layer Interaction
+The infrastructure layer depends on interfaces defined in the application layer rather than the other way around. This ensures that the core logic of the system is not directly tied to specific implementations. As a result, changes to external systems such as APIs or storage mechanisms can be made without affecting the main application logic.
+
+## Loose Coupling and Modularity
+The structure supports loose coupling by separating responsibilities across layers and using interfaces between them. This means that individual components can be modified or replaced without causing issues in other parts of the system. The package structure reflects this separation, with distinct layers for presentation, application, domain, and infrastructure.
+
+## Testability and Scalability
+The dependency structure also improves testability, as components can be tested independently by using interfaces instead of concrete implementations. It also supports scalability, since new features or components can be added without disrupting the existing system. This makes the design more suitable for future development.
+
+## Summary
+Overall, the dependency structure is clear, logical, and well organised. It avoids unnecessary dependencies, maintains loose coupling, and supports both testing and future growth of the system.
diff --git a/ArchitecturalDesign/UseCase.md b/ArchitecturalDesign/UseCase.md
new file mode 100644
index 0000000..14e0a30
--- /dev/null
+++ b/ArchitecturalDesign/UseCase.md
@@ -0,0 +1,41 @@
+# Use Case Model
+
+## Overview
+This use case model describes how the user interacts with the Share Price Comparison Web App. It focuses on the main tasks the user can perform and how the system responds to those actions. The diagram identifies the key use cases and shows how some actions depend on others.
+
+## Use Case Diagram
+
+
+## Main Use Cases
+The user can retrieve share price data, compare share prices, and view share price charts. These represent the main goals of the user when using the application.
+
+The system also carries out supporting actions such as storing price data and retrieving cached data. These actions are not directly triggered by the user but are required for the system to function properly and to support offline use.
+
+## Use Case Description: Compare Share Prices
+
+### Actor
+User
+
+### Description
+This use case allows the user to compare the share prices of one or two companies over a selected date range. The system retrieves the relevant data and presents it in a chart so that the user can easily compare performance over time.
+
+### Precondition
+The user has access to the application and enters valid share symbols and a date range within the allowed limit.
+
+### Main Flow
+1. The user enters one or two share symbols.
+2. The system validates the input.
+3. The user selects a date range.
+4. The system retrieves share price data for the selected shares from an external source.
+5. The system stores the retrieved data locally for future use.
+6. The system processes the data to prepare it for comparison.
+7. The system generates a chart based on the processed data.
+8. The system displays the chart to the user.
+
+### Alternative Flow
+If there is no internet connection, the system retrieves previously stored data instead of fetching new data.
+
+If the user enters invalid share symbols or an invalid date range, the system displays an error message and requests valid input.
+
+### Postcondition
+The user is presented with a chart showing the comparison of share prices over the selected time period, and the data may be stored for later use.
diff --git a/ArchitecturalDesign/component-diagram.png b/ArchitecturalDesign/component-diagram.png
new file mode 100644
index 0000000..da42037
Binary files /dev/null and b/ArchitecturalDesign/component-diagram.png differ
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index b5919c0..508c5b3 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -138,7 +138,7 @@ Develop architecture from requirements using formal models
### Member Responsibilities
-**Member A**
+**Member A - Azlan**
- Create Business Concept Model
- Create Use Case Diagram
- Write detailed use case descriptions
diff --git a/Meeting-Documentation/Meeting-4.md b/Meeting-Documentation/Meeting-4.md
new file mode 100644
index 0000000..d6e9510
--- /dev/null
+++ b/Meeting-Documentation/Meeting-4.md
@@ -0,0 +1,41 @@
+# Meeting Report — 06/03/2026 (13:00–14:00)
+
+## Project
+**Stock Comparison Application**
+
+## Meeting Goal
+- Finalise system architecture
+- Make sure it follows Clean Architecture
+- Review business type model
+
+## Roles
+- **Facilitator:** Luke Pring
+- **Note taker:** Sameer Shabbir
+
+## Attendees
+- Luke Pring
+- Jack Turner
+- Azlan Rashid
+- Sameer Shabbir
+
+## Roundtable Updates
+- **Luke:** Advised to base the business type model on the business concept model
+- **Jack:** Worked on UI and reviewed system structure
+- **Azlan:** Finalised architecture diagram
+- **Sameer:** Updated meeting notes and GitHub
+
+## Discussion points
+- Confirmed layered architecture (presentation, application, infrastructure)
+- Agreed to use interfaces for better structure
+- Reviewed system flow (UI → Controller → Service → Data)
+- Confirmed use of API + cache for data
+
+## Actions
+- Upload architecture diagram (**Sameer**)
+- Complete business type model (**Azlan**)
+- Continue UI work (**Jack**)
+- Review and confirm architecture design (**Luke**)
+- Update GitHub (**All**)
+
+## Outcome
+Architecture completed and uploaded. System follows a clear layered structure and meets Sprint 2 requirements.
diff --git a/stockscope/src/main/java/com/sharecomparison/application/CompareSharesUseCase.java b/stockscope/src/main/java/com/sharecomparison/application/CompareSharesUseCase.java
new file mode 100644
index 0000000..bc3f00e
--- /dev/null
+++ b/stockscope/src/main/java/com/sharecomparison/application/CompareSharesUseCase.java
@@ -0,0 +1,28 @@
+package com.sharecomparison.application;
+
+import com.sharecomparison.domain.ChartData;
+import com.sharecomparison.domain.ComparisonResult;
+import com.sharecomparison.domain.PriceData;
+import org.springframework.stereotype.Component;
+
+import java.time.LocalDate;
+import java.util.List;
+
+@Component
+public class CompareSharesUseCase {
+
+ private final IChartBuilder chartBuilder;
+
+ public CompareSharesUseCase(IChartBuilder chartBuilder) {
+ this.chartBuilder = chartBuilder;
+ }
+
+ public ComparisonResult compare(String symbol1, String symbol2,
+ LocalDate startDate, LocalDate endDate,
+ List data1, List data2) {
+
+ ChartData chartData = chartBuilder.buildChart(data1, data2);
+
+ return new ComparisonResult(symbol1, symbol2, startDate, endDate, data1, data2, chartData);
+ }
+}
diff --git a/stockscope/src/main/java/com/sharecomparison/application/FetchSharePricesUseCase.java b/stockscope/src/main/java/com/sharecomparison/application/FetchSharePricesUseCase.java
new file mode 100644
index 0000000..495923a
--- /dev/null
+++ b/stockscope/src/main/java/com/sharecomparison/application/FetchSharePricesUseCase.java
@@ -0,0 +1,38 @@
+package com.sharecomparison.application;
+
+import com.sharecomparison.domain.PriceData;
+import com.sharecomparison.infrastructure.ICacheStore;
+import com.sharecomparison.infrastructure.IMarketDataClient;
+import org.springframework.stereotype.Component;
+
+import java.time.LocalDate;
+import java.util.List;
+
+@Component
+public class FetchSharePricesUseCase {
+
+ private final ICacheStore cacheStore;
+ private final IMarketDataClient marketDataClient;
+
+ public FetchSharePricesUseCase(ICacheStore cacheStore, IMarketDataClient marketDataClient) {
+ this.cacheStore = cacheStore;
+ this.marketDataClient = marketDataClient;
+ }
+
+ public List fetch(String symbol, LocalDate startDate, LocalDate endDate) {
+ String cacheKey = symbol + ":" + startDate + ":" + endDate;
+
+ List cached = cacheStore.load(cacheKey);
+ if (cached != null && !cached.isEmpty()) {
+ return cached;
+ }
+
+ List fetched = marketDataClient.fetch(symbol, startDate, endDate);
+
+ if (fetched != null && !fetched.isEmpty()) {
+ cacheStore.save(cacheKey, fetched);
+ }
+
+ return fetched;
+ }
+}
diff --git a/stockscope/src/main/java/com/sharecomparison/application/PriceComparisonService.java b/stockscope/src/main/java/com/sharecomparison/application/PriceComparisonService.java
index 14cb8fa..aefe521 100644
--- a/stockscope/src/main/java/com/sharecomparison/application/PriceComparisonService.java
+++ b/stockscope/src/main/java/com/sharecomparison/application/PriceComparisonService.java
@@ -1,10 +1,7 @@
package com.sharecomparison.application;
-import com.sharecomparison.domain.ChartData;
import com.sharecomparison.domain.ComparisonResult;
import com.sharecomparison.domain.PriceData;
-import com.sharecomparison.infrastructure.ICacheStore;
-import com.sharecomparison.infrastructure.IMarketDataClient;
import org.springframework.stereotype.Service;
import java.time.LocalDate;
@@ -13,29 +10,38 @@
@Service
public class PriceComparisonService implements IPriceComparisonService {
- private final ICacheStore cacheStore;
- private final IMarketDataClient marketDataClient;
- private final IChartBuilder chartBuilder;
+ private final FetchSharePricesUseCase fetchSharePricesUseCase;
+ private final CompareSharesUseCase compareSharesUseCase;
- public PriceComparisonService(ICacheStore cacheStore,
- IMarketDataClient marketDataClient,
- IChartBuilder chartBuilder) {
- this.cacheStore = cacheStore;
- this.marketDataClient = marketDataClient;
- this.chartBuilder = chartBuilder;
+ public PriceComparisonService(FetchSharePricesUseCase fetchSharePricesUseCase,
+ CompareSharesUseCase compareSharesUseCase) {
+ this.fetchSharePricesUseCase = fetchSharePricesUseCase;
+ this.compareSharesUseCase = compareSharesUseCase;
}
@Override
public ComparisonResult compare(String symbol1, String symbol2,
LocalDate startDate, LocalDate endDate) {
- List data1 = marketDataClient.fetch(symbol1, startDate, endDate);
- List data2 = marketDataClient.fetch(symbol2, startDate, endDate);
+ validateDateRange(startDate, endDate);
- cacheStore.save(symbol1, data1);
- cacheStore.save(symbol2, data2);
+ List data1 = fetchSharePricesUseCase.fetch(symbol1, startDate, endDate);
+ List data2 = fetchSharePricesUseCase.fetch(symbol2, startDate, endDate);
- ChartData chartData = chartBuilder.buildChart(data1, data2);
- return new ComparisonResult(symbol1, symbol2, startDate, endDate, data1, data2, chartData);
+ return compareSharesUseCase.compare(symbol1, symbol2, startDate, endDate, data1, data2);
}
-}
+
+ private void validateDateRange(LocalDate start, LocalDate end) {
+ if (start == null || end == null) {
+ throw new IllegalArgumentException("Start and End dates must be provided.");
+ }
+
+ if (start.plusYears(2).isBefore(end)) {
+ throw new IllegalArgumentException("The maximum date range permitted is two years.");
+ }
+
+ if (start.isAfter(end)) {
+ throw new IllegalArgumentException("Start date cannot be after end date.");
+ }
+ }
+}
\ No newline at end of file
diff --git a/stockscope/src/main/java/com/sharecomparison/infrastructure/ICacheStore.java b/stockscope/src/main/java/com/sharecomparison/infrastructure/ICacheStore.java
index b93f607..56d1f6a 100644
--- a/stockscope/src/main/java/com/sharecomparison/infrastructure/ICacheStore.java
+++ b/stockscope/src/main/java/com/sharecomparison/infrastructure/ICacheStore.java
@@ -1,8 +1,9 @@
package com.sharecomparison.infrastructure;
-public interface ICacheStore {
-
- void save(String key, Object data);
+import com.sharecomparison.domain.PriceData;
+import java.util.List;
- Object load(String key);
+public interface ICacheStore {
+ void save(String key, List data);
+ List load(String key);
}
\ No newline at end of file
diff --git a/stockscope/src/main/java/com/sharecomparison/infrastructure/LocalCacheStore.java b/stockscope/src/main/java/com/sharecomparison/infrastructure/LocalCacheStore.java
index 2ea0c76..cbb4824 100644
--- a/stockscope/src/main/java/com/sharecomparison/infrastructure/LocalCacheStore.java
+++ b/stockscope/src/main/java/com/sharecomparison/infrastructure/LocalCacheStore.java
@@ -1,22 +1,24 @@
package com.sharecomparison.infrastructure;
+import com.sharecomparison.domain.PriceData;
import org.springframework.stereotype.Component;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
@Component
public class LocalCacheStore implements ICacheStore {
- private final Map cache = new HashMap<>();
+ private final Map> cache = new HashMap<>();
@Override
- public void save(String key, Object data) {
+ public void save(String key, List data) {
cache.put(key, data);
}
@Override
- public Object load(String key) {
+ public List load(String key) {
return cache.get(key);
}
}
diff --git a/stockscope/src/main/java/com/sharecomparison/presentation/WebPageController.java b/stockscope/src/main/java/com/sharecomparison/presentation/WebPageController.java
index cc5a273..a4c2e1e 100644
--- a/stockscope/src/main/java/com/sharecomparison/presentation/WebPageController.java
+++ b/stockscope/src/main/java/com/sharecomparison/presentation/WebPageController.java
@@ -91,4 +91,3 @@ public String handleDateParseError(MethodArgumentTypeMismatchException ex, Model
return "index";
}
}
-}
diff --git a/stockscope/src/main/resources/templates/index.html b/stockscope/src/main/resources/templates/index.html
index aeaa569..695e766 100644
--- a/stockscope/src/main/resources/templates/index.html
+++ b/stockscope/src/main/resources/templates/index.html
@@ -3,7 +3,7 @@
- Software Architecture and Design
+ Share Price Comparison
-
-
Software Architecture and Design
-
-
-
-
-
-
-
-
-
-
-
-
+
+
Share Price Comparison
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
Date
Close
-
-
-
-
-
-
-
-
-
-
-
-
-
Date
Close
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
Date
+
Close
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Date
+
Close
+
+
+
+
+
+
+
+
+
+
+
-
-
- Enter two stock symbols and a date range above to see live historical comparison.
+
+ Enter two stock symbols and a date range above to see live historical comparison.
+