private void AddHelicopter() { // TESTING Console.WriteLine("Entered Add Heli..."); Position start = new Position(-37.9061137, 176.2050742); Position end = new Position(-36.8613687, 174.7676895); Console.WriteLine("Set postitions..."); Helicopter heli = new Helicopter() { startPosition = start, destinationPosition = end }; Console.WriteLine("Created Heli..."); CustomPin heliPin = new CustomPin { CustomType = ODMSPinType.HELICOPTER, Label = "Heli", HelicopterDetails = heli, Position = heli.startPosition, Address = "1" }; Console.WriteLine("Created Helipin..."); customMap.HelicopterPins.Add(heliPin.Address, heliPin); customMap.Pins.Add(heliPin); }
/// <summary> /// Refreshes the flight path if the helicopter is currently selected /// </summary> /// <param name="heliPin"></param> private void refreshFlightDetails(CustomPin heliPin) { if (heliPin.Address.Equals(selectedHeli)) { clearFlightPath(); clearOrganRange(); if (!heliPin.HelicopterDetails.hasArrived(heliPin.Position)) { addFlightPath(heliPin); addOrganRange(heliPin); } } }
private async Task InitialiseHospitals() { ClinicianAPI clinicianApi = new ClinicianAPI(); Tuple <HttpStatusCode, List <Hospital> > tuple = await clinicianApi.GetHospitals(); switch (tuple.Item1) { case HttpStatusCode.OK: Console.WriteLine("Organ map hospitals retrieved successfully"); hospitals = tuple.Item2; foreach (Hospital currentHospital in hospitals) { Console.WriteLine("Tracking positions"); Position finalPosition = new Position(currentHospital.latitude, currentHospital.longitude); var pin = new CustomPin { CustomType = ODMSPinType.HOSPITAL, Position = finalPosition, Label = currentHospital.name, Address = currentHospital.address, }; // We add to this list to track our pins with additional information (like hospital or donor) customMap.CustomPins.Add(pin.Position, pin); lock (customMap.Pins) { customMap.Pins.Add(pin); } } break; case HttpStatusCode.ServiceUnavailable: await DisplayAlert("", "Server unavailable, check connection", "OK"); break; case HttpStatusCode.InternalServerError: await DisplayAlert("", "Server error retrieving hospitals, please try again (500)", "OK"); break; } }
/// <summary> /// Adds a bubble that reflects the expiry range of a helicopter carrying organ /// </summary> /// <param name="heliPin"></param> private void addOrganRange(CustomPin heliPin) { var circleOptions = new CircleOptions(); circleOptions.InvokeCenter(new LatLng(heliPin.Position.Latitude, heliPin.Position.Longitude)); // TODO adjust to organ countdown circleOptions.InvokeRadius(40000); circleOptions.InvokeFillColor(0X660000FF); circleOptions.InvokeStrokeColor(0X660000FF); circleOptions.InvokeStrokeWidth(0); highlightedOrganRange = new Tuple <CustomPin, Circle>(heliPin, NativeMap.AddCircle(circleOptions)); }
/// <summary> /// Generates marker options for a pin that contains information about a helicopter /// </summary> /// <param name="pin"></param> /// <returns></returns> private MarkerOptions CreateHelicopterMarker(CustomPin pin) { refreshFlightDetails(pin); // Create basic options var marker = new MarkerOptions(); marker.SetPosition(new LatLng(pin.Position.Latitude, pin.Position.Longitude)); marker.SetTitle(pin.Label); // Snippet is set to store the unique heli identifier (dictionary key) so it can be recalled when searching for a customPin based on Marker marker.SetSnippet(pin.Address); marker.SetIcon(BitmapDescriptorFactory.FromBitmap(helicopterIcons[pin.OrganToTransport])); return(marker); }
/// <summary> /// Adds a polyline path based on helicopter destination and current position /// </summary> /// <param name="heliPin"></param> private void addFlightPath(CustomPin heliPin) { var currentFlightPathOptions = new PolylineOptions(); // Other colour constants can be found at https://developer.android.com/reference/android/graphics/Color#constants_1 int BLUE = -16776961; currentFlightPathOptions.InvokeColor(BLUE); // Add current position (start of path) currentFlightPathOptions.Add(new LatLng(heliPin.Position.Latitude, heliPin.Position.Longitude)); // Add destination position (end of path) currentFlightPathOptions.Add(new LatLng(heliPin.HelicopterDetails.destinationPosition.Latitude, heliPin.HelicopterDetails.destinationPosition.Longitude)); highlightedFlightPath = new Tuple <CustomPin, Polyline>(heliPin, NativeMap.AddPolyline(currentFlightPathOptions)); }
/// <summary> /// Toggles more details regarding a helicopter (organs + flight path) /// </summary> /// <param name="customPin"></param> private void processHelicopterTapped(CustomPin customPin) { clearFlightPath(); clearOrganRange(); // Heli is already highlighted, deselect if (customPin.Address.Equals(selectedHeli)) { // Reset selected heli selectedHeli = null; } else { selectedHeli = customPin.Address; addFlightPath(customPin); addOrganRange(customPin); } }
/// <summary> /// Generates marker options for a pin that contains information about a hospital /// </summary> /// <param name="pin"></param> /// <returns></returns> private MarkerOptions CreateHospitalMarker(CustomPin pin) { // Create basic options var marker = new MarkerOptions(); marker.SetPosition(new LatLng(pin.Position.Latitude, pin.Position.Longitude)); marker.SetTitle(pin.Label); marker.SetSnippet(pin.Address); // Create the image Bitmap imageBitmap = BitmapFactory.DecodeResource(Resources, Resource.Drawable.hospital_icon, bitmapOptions); // Scale the image imageBitmap = Bitmap.CreateScaledBitmap(imageBitmap, 110, 110, false); marker.SetIcon(BitmapDescriptorFactory.FromBitmap(imageBitmap)); return(marker); }
/// <summary> /// Creates a MarkerOptions for a new pin on the map /// </summary> /// <param name="pin"></param> /// <returns></returns> protected override MarkerOptions CreateMarker(Pin pin) { MarkerOptions markerToAddOptions = null; // Find the correlating custom pin to get our extra parameters CustomPin foundCustomPin = GetCustomPin(pin); switch (foundCustomPin.CustomType) { case ODMSPinType.DONOR: markerToAddOptions = CreateDonorMarker(foundCustomPin); break; case ODMSPinType.HOSPITAL: markerToAddOptions = CreateHospitalMarker(foundCustomPin); break; case ODMSPinType.HELICOPTER: markerToAddOptions = CreateHelicopterMarker(foundCustomPin); break; } return(markerToAddOptions); }
///// <summary> ///// Activated whenever focus is on this page ///// </summary> protected override async void OnAppearing() { customMap = new CustomMap { MapType = MapType.Street, WidthRequest = 100, HeightRequest = 100, }; customMap.CustomPins = new Dictionary <Position, CustomPin> { }; customMap.HelicopterPins = new Dictionary <String, CustomPin> { }; //Center on New Zealand var centerPosition = new Position(-41.626217, 172.361873); customMap.MoveToRegion(MapSpan.FromCenterAndRadius( centerPosition, Distance.FromMiles(500.0))); var stack = new StackLayout { Spacing = 0 }; stack.Children.Add(customMap); Content = stack; Title = "Available Donor Map"; //Get all the organs from the database //Create pins for every organ UserAPI userAPI = new UserAPI(); Tuple <HttpStatusCode, List <CustomMapObject> > tuple = await userAPI.GetOrgansForMap(); Console.WriteLine("Initialising hoppis...."); //await InitialiseHospitals(); Console.WriteLine("Adding HeliChopper..."); //AddHelicopter(); Console.WriteLine("HeliChopper success, entering switch"); switch (tuple.Item1) { case HttpStatusCode.OK: Console.WriteLine("Organ Map Objects Successfully received"); users = tuple.Item2; Geocoder geocoder = new Geocoder(); foreach (CustomMapObject user in users) { if (user.organs.Count == 0) { continue; } IEnumerable <Position> position = await geocoder.GetPositionsForAddressAsync(user.cityOfDeath + ", " + user.regionOfDeath + ", " + user.countryOfDeath); Position organPosition = new Position(); using (var sequenceEnum = position.GetEnumerator()) { while (sequenceEnum.MoveNext()) { organPosition = sequenceEnum.Current; } } Random rnd = new Random(); double randomNumberLongitude = rnd.NextDouble() / 50.00; double randomNumberLatitude = rnd.NextDouble() / 50.00; Position finalPosition = new Position(organPosition.Latitude + randomNumberLatitude, organPosition.Longitude + randomNumberLongitude); List <string> organIcons = new List <string>(); foreach (string organ in user.organs) { string organLower = organ.ToLower(); string imageString = ""; switch (organLower) { case ("pancreas"): imageString = "pancreas_icon.png"; break; case ("heart"): imageString = "heart_icon.png"; break; case ("liver"): imageString = "liver_icon.png"; break; case ("connective-tissue"): imageString = "tissue_icon.png"; break; case ("bone-marrow"): imageString = "bone_icon.png"; break; case ("skin"): imageString = "skin_icon.png"; break; case ("lung"): imageString = "lungs_icon.png"; break; case ("cornea"): imageString = "eye_icon.png"; break; case ("kidney"): imageString = "kidney_icon.png"; break; case ("intestine"): imageString = "intestines_icon.png"; break; case ("middle-ear"): imageString = "ear_icon.png"; break; case ("bone"): imageString = "bone_icon.png"; break; } organIcons.Add(imageString); } //Used so that we can get the id when we want to view the user organIcons.Add(user.id.ToString()); //SET GENDER ICON //Randomize man or woman photo //If other then set to a pin //If none then also set to a pin string genderIcon = ""; switch (user.gender) { case ("Male"): int number = rnd.Next(1, 15); genderIcon = "man" + number + ".png"; break; case ("Female"): number = rnd.Next(1, 12); genderIcon = "woman" + number + ".png"; break; case ("Other"): genderIcon = "other.png"; break; default: genderIcon = "other.png"; break; } //SET PROFILE PHOTO //Get profile photo from users uploaded photo (if there is one) string profilePhoto = ""; Tuple <HttpStatusCode, string> photoResponse = await userAPI.GetUserPhotoForMapObjects(user.id); if (photoResponse.Item1 != HttpStatusCode.OK) { Console.WriteLine("Failed to retrieve profile photo or no profile photo found."); Byte[] bytes; if (Device.RuntimePlatform == Device.Android) { } else { bytes = File.ReadAllBytes("donationIcon.png"); profilePhoto = Convert.ToBase64String(bytes); } } else { profilePhoto = photoResponse.Item2; } var pin = new CustomPin { CustomType = ODMSPinType.DONOR, Position = finalPosition, Label = user.firstName + " " + user.middleName + " " + user.lastName, Address = user.cityOfDeath + ", " + user.regionOfDeath + ", " + user.countryOfDeath, Url = String.Join(",", organIcons), genderIcon = genderIcon, userPhoto = profilePhoto, userId = user.id }; customMap.CustomPins.Add(pin.Position, pin); lock (customMap.Pins) { customMap.Pins.Add(pin); } } StartTimer(200); Console.WriteLine("Reached the end of OnAppearing"); break; case HttpStatusCode.ServiceUnavailable: await DisplayAlert("", "Server unavailable, check connection", "OK"); StartTimer(200); break; case HttpStatusCode.InternalServerError: await DisplayAlert("", "Server error retrieving organs, please try again (500)", "OK"); StartTimer(200); break; } }
/// <summary> /// Generates marker options for a pin that contains information about a donor /// </summary> /// <param name="pin"></param> /// <returns></returns> private MarkerOptions CreateDonorMarker(CustomPin pin) { var marker = new MarkerOptions(); marker.SetPosition(new LatLng(pin.Position.Latitude, pin.Position.Longitude)); marker.SetTitle(pin.Label); marker.SetSnippet(pin.Address); Bitmap imageBitmap; switch (pin.genderIcon) { case "man1.png": imageBitmap = BitmapFactory.DecodeResource(Resources, Resource.Drawable.man1, bitmapOptions); break; case "man2.png": imageBitmap = BitmapFactory.DecodeResource(Resources, Resource.Drawable.man2, bitmapOptions); break; case "man3.png": imageBitmap = BitmapFactory.DecodeResource(Resources, Resource.Drawable.man3, bitmapOptions); break; case "man4.png": imageBitmap = BitmapFactory.DecodeResource(Resources, Resource.Drawable.man4, bitmapOptions); break; case "man5.png": imageBitmap = BitmapFactory.DecodeResource(Resources, Resource.Drawable.man5, bitmapOptions); break; case "man6.png": imageBitmap = BitmapFactory.DecodeResource(Resources, Resource.Drawable.man6, bitmapOptions); break; case "man7.png": imageBitmap = BitmapFactory.DecodeResource(Resources, Resource.Drawable.man7, bitmapOptions); break; case "man8.png": imageBitmap = BitmapFactory.DecodeResource(Resources, Resource.Drawable.man8, bitmapOptions); break; case "man9.png": imageBitmap = BitmapFactory.DecodeResource(Resources, Resource.Drawable.man9, bitmapOptions); break; case "man10.png": imageBitmap = BitmapFactory.DecodeResource(Resources, Resource.Drawable.man10, bitmapOptions); break; case "man11.png": imageBitmap = BitmapFactory.DecodeResource(Resources, Resource.Drawable.man11, bitmapOptions); break; case "man12.png": imageBitmap = BitmapFactory.DecodeResource(Resources, Resource.Drawable.man12, bitmapOptions); break; case "man13.png": imageBitmap = BitmapFactory.DecodeResource(Resources, Resource.Drawable.man13, bitmapOptions); break; case "man14.png": imageBitmap = BitmapFactory.DecodeResource(Resources, Resource.Drawable.man14, bitmapOptions); break; case "woman1.png": imageBitmap = BitmapFactory.DecodeResource(Resources, Resource.Drawable.woman1, bitmapOptions); break; case "woman2.png": imageBitmap = BitmapFactory.DecodeResource(Resources, Resource.Drawable.woman2, bitmapOptions); break; case "woman3.png": imageBitmap = BitmapFactory.DecodeResource(Resources, Resource.Drawable.woman3, bitmapOptions); break; case "woman4.png": imageBitmap = BitmapFactory.DecodeResource(Resources, Resource.Drawable.woman4, bitmapOptions); break; case "woman5.png": imageBitmap = BitmapFactory.DecodeResource(Resources, Resource.Drawable.woman5, bitmapOptions); break; case "woman6.png": imageBitmap = BitmapFactory.DecodeResource(Resources, Resource.Drawable.woman6, bitmapOptions); break; case "woman7.png": imageBitmap = BitmapFactory.DecodeResource(Resources, Resource.Drawable.woman7, bitmapOptions); break; case "woman8.png": imageBitmap = BitmapFactory.DecodeResource(Resources, Resource.Drawable.woman8, bitmapOptions); break; case "woman9.png": imageBitmap = BitmapFactory.DecodeResource(Resources, Resource.Drawable.woman9, bitmapOptions); break; case "woman10.png": imageBitmap = BitmapFactory.DecodeResource(Resources, Resource.Drawable.woman10, bitmapOptions); break; case "woman11.png": imageBitmap = BitmapFactory.DecodeResource(Resources, Resource.Drawable.woman11, bitmapOptions); break; case "other.png": imageBitmap = BitmapFactory.DecodeResource(Resources, Resource.Drawable.other, bitmapOptions); break; default: imageBitmap = BitmapFactory.DecodeResource(Resources, Resource.Drawable.other, bitmapOptions); break; } Bitmap resizedBitmap; if (pin.genderIcon.Equals("other.png")) { resizedBitmap = Bitmap.CreateScaledBitmap(imageBitmap, 110, 110, false); } else { resizedBitmap = Bitmap.CreateScaledBitmap(imageBitmap, 120, 120, false); } marker.SetIcon(BitmapDescriptorFactory.FromBitmap(resizedBitmap)); return(marker); }