mirror of
https://github.com/SamyRai/turash.git
synced 2025-12-26 23:01:33 +00:00
Repository Structure:
- Move files from cluttered root directory into organized structure
- Create archive/ for archived data and scraper results
- Create bugulma/ for the complete application (frontend + backend)
- Create data/ for sample datasets and reference materials
- Create docs/ for comprehensive documentation structure
- Create scripts/ for utility scripts and API tools
Backend Implementation:
- Implement 3 missing backend endpoints identified in gap analysis:
* GET /api/v1/organizations/{id}/matching/direct - Direct symbiosis matches
* GET /api/v1/users/me/organizations - User organizations
* POST /api/v1/proposals/{id}/status - Update proposal status
- Add complete proposal domain model, repository, and service layers
- Create database migration for proposals table
- Fix CLI server command registration issue
API Documentation:
- Add comprehensive proposals.md API documentation
- Update README.md with Users and Proposals API sections
- Document all request/response formats, error codes, and business rules
Code Quality:
- Follow existing Go backend architecture patterns
- Add proper error handling and validation
- Match frontend expected response schemas
- Maintain clean separation of concerns (handler -> service -> repository)
181 lines
4.5 KiB
Go
181 lines
4.5 KiB
Go
package geospatial
|
|
|
|
import (
|
|
"math"
|
|
"testing"
|
|
)
|
|
|
|
func TestHaversineDistance(t *testing.T) {
|
|
calc := NewDistanceCalculator(DefaultConfig())
|
|
|
|
tests := []struct {
|
|
name string
|
|
p1 Point
|
|
p2 Point
|
|
wantDist float64
|
|
tolerance float64
|
|
}{
|
|
{
|
|
name: "Same point",
|
|
p1: Point{Latitude: 52.5200, Longitude: 13.4050}, // Berlin
|
|
p2: Point{Latitude: 52.5200, Longitude: 13.4050},
|
|
wantDist: 0.0,
|
|
tolerance: 0.001,
|
|
},
|
|
{
|
|
name: "Berlin to Munich",
|
|
p1: Point{Latitude: 52.5200, Longitude: 13.4050}, // Berlin
|
|
p2: Point{Latitude: 48.1351, Longitude: 11.5820}, // Munich
|
|
wantDist: 504.0, // Approximately 504 km
|
|
tolerance: 5.0,
|
|
},
|
|
{
|
|
name: "Short distance",
|
|
p1: Point{Latitude: 52.5200, Longitude: 13.4050},
|
|
p2: Point{Latitude: 52.5300, Longitude: 13.4150},
|
|
wantDist: 1.3, // Approximately 1.3 km
|
|
tolerance: 0.1,
|
|
},
|
|
{
|
|
name: "Cross equator",
|
|
p1: Point{Latitude: 10.0, Longitude: 0.0},
|
|
p2: Point{Latitude: -10.0, Longitude: 0.0},
|
|
wantDist: 2220.0, // Approximately 2220 km
|
|
tolerance: 10.0,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got, err := calc.HaversineDistance(tt.p1, tt.p2)
|
|
if err != nil {
|
|
t.Fatalf("HaversineDistance() error = %v", err)
|
|
}
|
|
|
|
if math.Abs(got-tt.wantDist) > tt.tolerance {
|
|
t.Errorf("HaversineDistance() = %v, want %v (tolerance: %v)", got, tt.wantDist, tt.tolerance)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestHaversineDistance_InvalidPoints(t *testing.T) {
|
|
calc := NewDistanceCalculator(DefaultConfig())
|
|
|
|
tests := []struct {
|
|
name string
|
|
p1 Point
|
|
p2 Point
|
|
}{
|
|
{
|
|
name: "Invalid latitude - too high",
|
|
p1: Point{Latitude: 91.0, Longitude: 0.0},
|
|
p2: Point{Latitude: 52.5200, Longitude: 13.4050},
|
|
},
|
|
{
|
|
name: "Invalid latitude - too low",
|
|
p1: Point{Latitude: -91.0, Longitude: 0.0},
|
|
p2: Point{Latitude: 52.5200, Longitude: 13.4050},
|
|
},
|
|
{
|
|
name: "Invalid longitude - too high",
|
|
p1: Point{Latitude: 52.5200, Longitude: 181.0},
|
|
p2: Point{Latitude: 52.5200, Longitude: 13.4050},
|
|
},
|
|
{
|
|
name: "Invalid longitude - too low",
|
|
p1: Point{Latitude: 52.5200, Longitude: -181.0},
|
|
p2: Point{Latitude: 52.5200, Longitude: 13.4050},
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
_, err := calc.HaversineDistance(tt.p1, tt.p2)
|
|
if err == nil {
|
|
t.Error("HaversineDistance() expected error for invalid point")
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestVincentyDistance(t *testing.T) {
|
|
config := DefaultConfig()
|
|
config.UseEllipsoidalModel = true
|
|
calc := NewDistanceCalculator(config)
|
|
|
|
tests := []struct {
|
|
name string
|
|
p1 Point
|
|
p2 Point
|
|
wantDist float64
|
|
tolerance float64
|
|
}{
|
|
{
|
|
name: "Same point",
|
|
p1: Point{Latitude: 52.5200, Longitude: 13.4050},
|
|
p2: Point{Latitude: 52.5200, Longitude: 13.4050},
|
|
wantDist: 0.0,
|
|
tolerance: 0.001,
|
|
},
|
|
{
|
|
name: "Berlin to Munich",
|
|
p1: Point{Latitude: 52.5200, Longitude: 13.4050}, // Berlin
|
|
p2: Point{Latitude: 48.1351, Longitude: 11.5820}, // Munich
|
|
wantDist: 504.0, // Approximately 504 km
|
|
tolerance: 5.0,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got, err := calc.VincentyDistance(tt.p1, tt.p2)
|
|
if err != nil {
|
|
t.Fatalf("VincentyDistance() error = %v", err)
|
|
}
|
|
|
|
if math.Abs(got-tt.wantDist) > tt.tolerance {
|
|
t.Errorf("VincentyDistance() = %v, want %v (tolerance: %v)", got, tt.wantDist, tt.tolerance)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestCalculateDistance(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
method string
|
|
p1 Point
|
|
p2 Point
|
|
wantDist float64
|
|
tolerance float64
|
|
}{
|
|
{
|
|
name: "Haversine method",
|
|
method: "haversine",
|
|
p1: Point{Latitude: 52.5200, Longitude: 13.4050},
|
|
p2: Point{Latitude: 52.5300, Longitude: 13.4150},
|
|
wantDist: 1.3,
|
|
tolerance: 0.1,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
config := DefaultConfig()
|
|
config.DefaultDistanceMethod = tt.method
|
|
calc := NewDistanceCalculator(config)
|
|
|
|
impl := calc.(*DistanceCalculatorImpl)
|
|
got, err := impl.CalculateDistance(tt.p1, tt.p2)
|
|
if err != nil {
|
|
t.Fatalf("CalculateDistance() error = %v", err)
|
|
}
|
|
|
|
if math.Abs(got-tt.wantDist) > tt.tolerance {
|
|
t.Errorf("CalculateDistance() = %v, want %v (tolerance: %v)", got, tt.wantDist, tt.tolerance)
|
|
}
|
|
})
|
|
}
|
|
}
|