Compare commits
	
		
			1 Commits
		
	
	
		
			d4de945df8
			...
			dd48fda99f
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| dd48fda99f | 
							
								
								
									
										111
									
								
								backend/test.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								backend/test.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,111 @@
 | 
			
		||||
import numpy as np
 | 
			
		||||
 | 
			
		||||
def euclidean_distance(p1, p2):
 | 
			
		||||
    print(p1, p2)
 | 
			
		||||
    return np.sqrt((p1[0] - p2[0])**2 + (p1[1] - p2[1])**2)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def maximize_score(places, max_distance, fixed_entry, top_k=3):
 | 
			
		||||
    """
 | 
			
		||||
    Maximizes the total score of visited places while staying below the maximum distance.
 | 
			
		||||
    
 | 
			
		||||
    Parameters:
 | 
			
		||||
    places (list of tuples): Each tuple contains (score, (x, y), location).
 | 
			
		||||
    max_distance (float): The maximum distance that can be traveled.
 | 
			
		||||
    fixed_entry (tuple): The place that needs to be visited independently of its score.
 | 
			
		||||
    top_k (int): Number of top candidates to consider in each iteration.
 | 
			
		||||
    
 | 
			
		||||
    Returns:
 | 
			
		||||
    list of tuples: The visited places.
 | 
			
		||||
    float: The total score of the visited places.
 | 
			
		||||
    """
 | 
			
		||||
    # Initialize total distance and score
 | 
			
		||||
    total_distance = 0
 | 
			
		||||
    total_score = 0
 | 
			
		||||
    visited_places = []
 | 
			
		||||
 | 
			
		||||
    # Add the fixed entry to the visited list
 | 
			
		||||
    score, (x, y), _ = fixed_entry
 | 
			
		||||
    visited_places.append(fixed_entry)
 | 
			
		||||
    total_score += score
 | 
			
		||||
 | 
			
		||||
    # Remove the fixed entry from the list of places
 | 
			
		||||
    remaining_places = [place for place in places if place != fixed_entry]
 | 
			
		||||
 | 
			
		||||
    # Sort remaining places by score-to-distance ratio
 | 
			
		||||
    
 | 
			
		||||
    remaining_places.sort(key=lambda p: p[0] / euclidean_distance((x, y), (p[1][0], p[1][1])), reverse=True)
 | 
			
		||||
 | 
			
		||||
    # Add places to the visited list if they don't exceed the maximum distance
 | 
			
		||||
    current_location = (x, y)
 | 
			
		||||
    while remaining_places and total_distance < max_distance:
 | 
			
		||||
        # Consider top_k candidates
 | 
			
		||||
        candidates = remaining_places[:top_k]
 | 
			
		||||
        best_candidate = None
 | 
			
		||||
        best_score_increase = -np.inf
 | 
			
		||||
 | 
			
		||||
        for candidate in candidates:
 | 
			
		||||
            score, (cx, cy), location = candidate
 | 
			
		||||
            distance = euclidean_distance(current_location, (cx, cy))
 | 
			
		||||
            if total_distance + distance <= max_distance:
 | 
			
		||||
                score_increase = score / distance
 | 
			
		||||
                if score_increase > best_score_increase:
 | 
			
		||||
                    best_score_increase = score_increase
 | 
			
		||||
                    best_candidate = candidate
 | 
			
		||||
 | 
			
		||||
        if best_candidate:
 | 
			
		||||
            visited_places.append(best_candidate)
 | 
			
		||||
            total_distance += euclidean_distance(current_location, best_candidate[1])
 | 
			
		||||
            total_score += best_candidate[0]
 | 
			
		||||
            current_location = best_candidate[1]
 | 
			
		||||
            remaining_places.remove(best_candidate)
 | 
			
		||||
        else:
 | 
			
		||||
            break
 | 
			
		||||
 | 
			
		||||
    return visited_places, total_score
 | 
			
		||||
 | 
			
		||||
# Example usage
 | 
			
		||||
places = [
 | 
			
		||||
    (10, (0, 0), 'A'),
 | 
			
		||||
    (8, (4, 2), 'B'),
 | 
			
		||||
    (15, (6, 4), 'C'),
 | 
			
		||||
    (7, (5, 6), 'D'),
 | 
			
		||||
    (12, (1, 8), 'E'),
 | 
			
		||||
    (14, (34, 10), 'F'),
 | 
			
		||||
    (15, (65, 12), 'G'),
 | 
			
		||||
    (12, (3, 14), 'H'),
 | 
			
		||||
    (12, (15, 1), 'I'),
 | 
			
		||||
    (7, (17, 4), 'J'),
 | 
			
		||||
    (12, (3, 3), 'K'),
 | 
			
		||||
    (4, (21, 22), 'L'),
 | 
			
		||||
    (12, (23, 24), 'M'),
 | 
			
		||||
    (4, (25, 26), 'N'),
 | 
			
		||||
    (2, (27, 28), 'O'),
 | 
			
		||||
]
 | 
			
		||||
fixed_entry = (10, (0, 0), 'A')
 | 
			
		||||
max_distance = 50
 | 
			
		||||
 | 
			
		||||
visited_places, total_score = maximize_score(places, max_distance, fixed_entry)
 | 
			
		||||
print("Visited Places:", visited_places)
 | 
			
		||||
print("Total Score:", total_score)
 | 
			
		||||
 | 
			
		||||
import matplotlib.pyplot as plt
 | 
			
		||||
 | 
			
		||||
# Plot the route
 | 
			
		||||
def plot_route(visited_places):
 | 
			
		||||
    x_coords = [place[1][0] for place in visited_places]
 | 
			
		||||
    y_coords = [place[1][1] for place in visited_places]
 | 
			
		||||
    labels = [place[2] for place in visited_places]
 | 
			
		||||
 | 
			
		||||
    plt.figure(figsize=(10, 6))
 | 
			
		||||
    plt.plot(x_coords, y_coords, marker='o', linestyle='-', color='b')
 | 
			
		||||
    for i, label in enumerate(labels):
 | 
			
		||||
        plt.text(x_coords[i], y_coords[i], label, fontsize=12, ha='right')
 | 
			
		||||
 | 
			
		||||
    plt.title('Route of Visited Places')
 | 
			
		||||
    plt.xlabel('X Coordinate')
 | 
			
		||||
    plt.ylabel('Y Coordinate')
 | 
			
		||||
    plt.grid(True)
 | 
			
		||||
    plt.savefig('route.png')
 | 
			
		||||
 | 
			
		||||
plot_route(visited_places)
 | 
			
		||||
@@ -34,29 +34,85 @@ Widget loadingText(Trip trip) => FutureBuilder(
 | 
			
		||||
    Widget greeter;
 | 
			
		||||
 | 
			
		||||
    if (snapshot.hasData) {
 | 
			
		||||
      greeter = AutoSizeText(
 | 
			
		||||
        maxLines: 1,
 | 
			
		||||
        'Generating your trip to ${snapshot.data}...',
 | 
			
		||||
      greeter = AnimatedGradientText(
 | 
			
		||||
        text: 'Generating your trip to ${snapshot.data}...',
 | 
			
		||||
        style: greeterStyle,
 | 
			
		||||
      );
 | 
			
		||||
    } else if (snapshot.hasError) {
 | 
			
		||||
      // the exact error is shown in the central part of the trip overview. No need to show it here
 | 
			
		||||
      greeter = AutoSizeText(
 | 
			
		||||
        maxLines: 1,
 | 
			
		||||
        'Error while loading trip.',
 | 
			
		||||
      greeter = AnimatedGradientText(
 | 
			
		||||
        text: 'Error while loading trip.',
 | 
			
		||||
        style: greeterStyle,
 | 
			
		||||
        );
 | 
			
		||||
      );
 | 
			
		||||
    } else {
 | 
			
		||||
      greeter = AutoSizeText(
 | 
			
		||||
        maxLines: 1,
 | 
			
		||||
        'Generating your trip...',
 | 
			
		||||
      greeter = AnimatedGradientText(
 | 
			
		||||
        text: 'Generating your trip...',
 | 
			
		||||
        style: greeterStyle,
 | 
			
		||||
        );
 | 
			
		||||
      );
 | 
			
		||||
    }
 | 
			
		||||
    return greeter;
 | 
			
		||||
  }
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
class AnimatedGradientText extends StatefulWidget {
 | 
			
		||||
  final String text;
 | 
			
		||||
  final TextStyle style;
 | 
			
		||||
 | 
			
		||||
  const AnimatedGradientText({
 | 
			
		||||
    Key? key,
 | 
			
		||||
    required this.text,
 | 
			
		||||
    required this.style,
 | 
			
		||||
  }) : super(key: key);
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  _AnimatedGradientTextState createState() => _AnimatedGradientTextState();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class _AnimatedGradientTextState extends State<AnimatedGradientText> with SingleTickerProviderStateMixin {
 | 
			
		||||
  late AnimationController _controller;
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  void initState() {
 | 
			
		||||
    super.initState();
 | 
			
		||||
    _controller = AnimationController(
 | 
			
		||||
      duration: const Duration(seconds: 1),
 | 
			
		||||
      vsync: this,
 | 
			
		||||
    )..repeat();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  void dispose() {
 | 
			
		||||
    _controller.dispose();
 | 
			
		||||
    super.dispose();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    return AnimatedBuilder(
 | 
			
		||||
      animation: _controller,
 | 
			
		||||
      builder: (context, child) {
 | 
			
		||||
        return ShaderMask(
 | 
			
		||||
          shaderCallback: (bounds) {
 | 
			
		||||
            return LinearGradient(
 | 
			
		||||
              colors: [Colors.blue, Colors.red, Colors.blue],
 | 
			
		||||
              stops: [
 | 
			
		||||
                _controller.value - 1.0,
 | 
			
		||||
                _controller.value,
 | 
			
		||||
                _controller.value + 1.0,
 | 
			
		||||
              ],
 | 
			
		||||
              tileMode: TileMode.mirror,
 | 
			
		||||
            ).createShader(bounds);
 | 
			
		||||
          },
 | 
			
		||||
          child: Text(
 | 
			
		||||
            widget.text,
 | 
			
		||||
            style: widget.style,
 | 
			
		||||
          ),
 | 
			
		||||
        );
 | 
			
		||||
      },
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -125,7 +125,7 @@ class LandmarkType {
 | 
			
		||||
  LandmarkType({required this.name, this.icon = const Icon(Icons.location_on)}) {
 | 
			
		||||
    switch (name) {
 | 
			
		||||
      case 'sightseeing':
 | 
			
		||||
        icon = const Icon(Icons.church);
 | 
			
		||||
        icon = const Icon(Icons.castle);
 | 
			
		||||
        break;
 | 
			
		||||
      case 'nature':
 | 
			
		||||
        icon = const Icon(Icons.eco);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user