def CheckSanity(self):
        """ Started out as a function that checked to make sure the activity itself is sane.
            Now we perform a lot of checks to make sure all the objects were initialized properly
            I'm undecided on this front...
                - Forcing the .NET model of "XYZCollection"s that enforce integrity seems wrong
                - Enforcing them in constructors makes using the classes a pain
        """
        if "ServiceDataCollection" in self.__dict__:
            srcs = self.ServiceDataCollection  # this is just so I can see the source of the activity in the exception message
        if len(self.Laps) == 0:
                raise ValueError("No laps")
        wptCt = sum([len(x.Waypoints) for x in self.Laps])
        if self.Stationary is None:
            raise ValueError("Activity is undecidedly stationary")
        if self.GPS is None:
            raise ValueError("Activity is undecidedly GPS-tracked")
        if not self.Stationary:
            if wptCt == 0:
                raise ValueError("Exactly 0 waypoints")
            if wptCt == 1:
                raise ValueError("Only 1 waypoint")
        if self.Stats.Distance.Value is not None and self.Stats.Distance.asUnits(ActivityStatisticUnit.Meters).Value > 1000 * 1000:
            raise ValueError("Exceedingly long activity (distance)")
        if self.StartTime.replace(tzinfo=None) > (datetime.now() + timedelta(days=5)):
            raise ValueError("Activity is from the future")
        if self.StartTime.replace(tzinfo=None) < datetime(1995, 1, 1):
            raise ValueError("Activity falls implausibly far in the past")
        if self.EndTime and self.EndTime.replace(tzinfo=None) > (datetime.now() + timedelta(days=5 + 5)): # Based on the 5-day activity length limit imposed later.
            raise ValueError("Activity ends in the future")

        if self.StartTime and self.EndTime:
            # We can only do these checks if the activity has both start and end times (Dropbox)
            if (self.EndTime - self.StartTime).total_seconds() < 0:
                raise ValueError("Event finishes before it starts")
            if (self.EndTime - self.StartTime).total_seconds() == 0:
                raise ValueError("0-duration activity")
            if (self.EndTime - self.StartTime).total_seconds() > 60 * 60 * 24 * 5:
                raise ValueError("Exceedingly long activity (time)")

        if len(self.Laps) == 1:
            if self.Laps[0].Stats != self.Stats:
                raise ValueError("Activity with 1 lap has mismatching statistics between activity and lap")
        altLow = None
        altHigh = None
        pointsWithLocation = 0
        unpausedPoints = 0
        for lap in self.Laps:
            if not lap.StartTime:
                raise ValueError("Lap has no start time")
            if not lap.EndTime:
                raise ValueError("Lap has no end time")
            for wp in lap.Waypoints:
                if wp.Type != WaypointType.Pause:
                    unpausedPoints += 1
                if wp.Location:
                    if wp.Location.Latitude == 0 and wp.Location.Longitude == 0:
                        raise ValueError("Invalid lat/lng")
                    if (wp.Location.Latitude is not None and (wp.Location.Latitude > 90 or wp.Location.Latitude < -90)) or (wp.Location.Longitude is not None and (wp.Location.Longitude > 180 or wp.Location.Longitude < -180)):
                        raise ValueError("Out of range lat/lng")
                    if wp.Location.Altitude is not None and (altLow is None or wp.Location.Altitude < altLow):
                        altLow = wp.Location.Altitude
                    if wp.Location.Altitude is not None and (altHigh is None or wp.Location.Altitude > altHigh):
                        altHigh = wp.Location.Altitude
                if wp.Location and wp.Location.Latitude is not None and wp.Location.Longitude is not None:
                    pointsWithLocation += 1
        if unpausedPoints == 1:
            raise ValueError("0 < n <= 1 unpaused points in activity")
        if pointsWithLocation == 1:
            raise ValueError("0 < n <= 1 geographic points in activity") # Make RK happy
        if altLow is not None and altLow == altHigh and altLow == 0:  # some activities have very sporadic altitude data, we'll let it be...
            raise ValueError("Invalid altitudes / no change from " + str(altLow))
 Started out as a function that checked to make sure the activity itself is sane.
            Now we perform a lot of checks to make sure all the objects were initialized properly
            I'm undecided on this front...
                - Forcing the .NET model of "XYZCollection"s that enforce integrity seems wrong
                - Enforcing them in constructors makes using the classes a pain
        
tapiriik/services/interchange.py