746 lines
38 KiB
Plaintext
746 lines
38 KiB
Plaintext
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Microsoft Research Singularity
|
||
|
//
|
||
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||
|
//
|
||
|
// File: MapDemo.sg
|
||
|
//
|
||
|
// Note: A demo web application that uses the MapPointProxy service to render
|
||
|
// maps
|
||
|
//
|
||
|
|
||
|
using Microsoft.SingSharp;
|
||
|
using Microsoft.SingSharp.Runtime;
|
||
|
using Microsoft.Singularity.Channels;
|
||
|
using Microsoft.Singularity.Directory;
|
||
|
using Microsoft.Singularity.WebApps;
|
||
|
using Microsoft.Singularity.WebApps.Contracts;
|
||
|
using Microsoft.Singularity.MapPointProxy.Contracts;
|
||
|
using Microsoft.Singularity.SeattleTrafficProxy.Contracts;
|
||
|
using System;
|
||
|
using System.Collections;
|
||
|
using System.Text;
|
||
|
using System.Web;
|
||
|
|
||
|
using Microsoft.Singularity.Io;
|
||
|
using Microsoft.Singularity.Configuration;
|
||
|
using Microsoft.SingSharp.Reflection;
|
||
|
using Microsoft.Singularity.Applications;
|
||
|
[assembly: Transform(typeof(WebAppResourceTransform))]
|
||
|
|
||
|
namespace Microsoft.Singularity.WebApps
|
||
|
{
|
||
|
[Category("WebApp")]
|
||
|
internal sealed class Parameters
|
||
|
{
|
||
|
[Endpoint]
|
||
|
public readonly TRef<WebAppContract.Exp:Start> webAppRef;
|
||
|
|
||
|
reflective private Parameters();
|
||
|
}
|
||
|
|
||
|
|
||
|
public class MapDemoWebApp : IWebApp
|
||
|
{
|
||
|
private TRef<MapPointProxyContract.Imp:ReadyState>! m_MapConn;
|
||
|
|
||
|
public MapDemoWebApp()
|
||
|
{
|
||
|
MapPointProxyContract.Imp! impMapConn;
|
||
|
MapPointProxyContract.Exp! expMapConn;
|
||
|
MapPointProxyContract.NewChannel(out impMapConn, out expMapConn);
|
||
|
|
||
|
DirectoryServiceContract.Imp epNS = DirectoryService.NewClientEndpoint();
|
||
|
|
||
|
try {
|
||
|
// Look up the MapPoint Proxy module
|
||
|
epNS.SendBind(Bitter.FromString2(MapPointProxyContract.ModuleName), expMapConn);
|
||
|
|
||
|
switch receive {
|
||
|
case epNS.NakBind(ServiceContract.Exp:Start rejectedEP, error) :
|
||
|
delete impMapConn;
|
||
|
delete rejectedEP;
|
||
|
throw new Exception("Couldn't connect to the MapPoint proxy module");
|
||
|
break;
|
||
|
|
||
|
case epNS.AckBind() :
|
||
|
impMapConn.RecvMapPointReady();
|
||
|
m_MapConn = new TRef<MapPointProxyContract.Imp:ReadyState>(impMapConn);
|
||
|
// success
|
||
|
break;
|
||
|
|
||
|
case epNS.ChannelClosed() :
|
||
|
throw new Exception("epNS channel closed");
|
||
|
}
|
||
|
}
|
||
|
finally {
|
||
|
delete epNS;
|
||
|
}
|
||
|
|
||
|
base();
|
||
|
}
|
||
|
|
||
|
public void ProcessRequest(IHttpRequest! request)
|
||
|
{
|
||
|
MapPointProxyContract.Imp impMapConn = m_MapConn.Acquire();
|
||
|
|
||
|
try {
|
||
|
string queryString = request.GetQueryString();
|
||
|
byte mask = 0xff;
|
||
|
|
||
|
if (queryString != null) {
|
||
|
const string maskPreamble = "mask=";
|
||
|
int maskOffset = queryString.IndexOf(maskPreamble);
|
||
|
|
||
|
if (maskOffset != -1) {
|
||
|
int semiOffset = queryString.IndexOf(';', maskOffset + maskPreamble.Length);
|
||
|
|
||
|
try {
|
||
|
if (semiOffset != -1) {
|
||
|
mask = Byte.Parse(queryString.Substring(maskOffset + maskPreamble.Length,
|
||
|
semiOffset - maskOffset - maskPreamble.Length));
|
||
|
}
|
||
|
else {
|
||
|
mask = Byte.Parse(queryString.Substring(maskOffset + maskPreamble.Length));
|
||
|
}
|
||
|
}
|
||
|
catch (Exception) {
|
||
|
// Ignore parse errors and keep a mask of 0xff
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Mark everything we serve as permanent
|
||
|
request.SendHeader("Expires", (!)DateTime.Now.AddYears(1).ToUniversalTime().ToString("R"));
|
||
|
request.SendHeader("Cache-Control", "max-age=" + (60 * 60 * 24 * 365).ToString()); // 1 year
|
||
|
|
||
|
if (request.GetUriPath().EndsWith("redmond.gif")) {
|
||
|
MapPointProxyContract.PushPin[]! in ExHeap pushPins =
|
||
|
BuildPushPins(RedmondPushPins, mask);
|
||
|
|
||
|
// Hard-coded map center and zoom factor
|
||
|
char[]! in ExHeap centerLat = Bitter.FromString2("47.664037990827104");
|
||
|
char[]! in ExHeap centerLong = Bitter.FromString2("-122.12025798221626");
|
||
|
|
||
|
ServeMap(request, impMapConn, centerLat, centerLong, 10, pushPins);
|
||
|
}
|
||
|
else if (request.GetUriPath().EndsWith("seattle.gif")) {
|
||
|
MapPointProxyContract.PushPin[]! in ExHeap pushPins =
|
||
|
BuildPushPins(SeattlePushPins, mask);
|
||
|
|
||
|
// Hard-coded map center and zoom factor
|
||
|
char[]! in ExHeap centerLat = Bitter.FromString2("47.616391194232195");
|
||
|
char[]! in ExHeap centerLong = Bitter.FromString2("-122.32471226177632");
|
||
|
|
||
|
ServeMap(request, impMapConn, centerLat, centerLong, 7, pushPins);
|
||
|
}
|
||
|
else if (request.GetUriPath().EndsWith("blue.bmp")) {
|
||
|
request.SendStatus(200, "OK");
|
||
|
request.SendHeader("Content-type", "image/x-ms-bmp");
|
||
|
request.SendBodyData(BlueIcon.ImageData);
|
||
|
}
|
||
|
else if (request.GetUriPath().EndsWith("red.bmp")) {
|
||
|
request.SendStatus(200, "OK");
|
||
|
request.SendHeader("Content-type", "image/x-ms-bmp");
|
||
|
request.SendBodyData(RedIcon.ImageData);
|
||
|
}
|
||
|
else if (request.GetUriPath().EndsWith("green.bmp")) {
|
||
|
request.SendStatus(200, "OK");
|
||
|
request.SendHeader("Content-type", "image/x-ms-bmp");
|
||
|
request.SendBodyData(GreenIcon.ImageData);
|
||
|
}
|
||
|
else if (request.GetUriPath().EndsWith("tower.bmp")) {
|
||
|
request.SendStatus(200, "OK");
|
||
|
request.SendHeader("Content-type", "image/x-ms-bmp");
|
||
|
request.SendBodyData(TowerIcon.ImageData);
|
||
|
}
|
||
|
else if (request.GetUriPath().EndsWith("seattle_all.htm")) {
|
||
|
request.SendStatus(200, "OK");
|
||
|
request.SendHeader("Content-type", "text/html");
|
||
|
request.SendBodyData(SeattleAllMapPage.HTMLData);
|
||
|
}
|
||
|
else if (request.GetUriPath().EndsWith("seattle_sbc.htm")) {
|
||
|
request.SendStatus(200, "OK");
|
||
|
request.SendHeader("Content-type", "text/html");
|
||
|
request.SendBodyData(SeattleSBCMapPage.HTMLData);
|
||
|
}
|
||
|
else if (request.GetUriPath().EndsWith("seattle_star.htm")) {
|
||
|
request.SendStatus(200, "OK");
|
||
|
request.SendHeader("Content-type", "text/html");
|
||
|
request.SendBodyData(SeattleStarMapPage.HTMLData);
|
||
|
}
|
||
|
else if (request.GetUriPath().EndsWith("seattle_tullys.htm")) {
|
||
|
request.SendStatus(200, "OK");
|
||
|
request.SendHeader("Content-type", "text/html");
|
||
|
request.SendBodyData(SeattleTullysMapPage.HTMLData);
|
||
|
}
|
||
|
else if (request.GetUriPath().EndsWith("redmond_all.htm")) {
|
||
|
request.SendStatus(200, "OK");
|
||
|
request.SendHeader("Content-type", "text/html");
|
||
|
request.SendBodyData(RedmondAllMapPage.HTMLData);
|
||
|
}
|
||
|
else if (request.GetUriPath().EndsWith("redmond_star.htm")) {
|
||
|
request.SendStatus(200, "OK");
|
||
|
request.SendHeader("Content-type", "text/html");
|
||
|
request.SendBodyData(RedmondStarMapPage.HTMLData);
|
||
|
}
|
||
|
else if (request.GetUriPath().EndsWith("redmond_sbc.htm")) {
|
||
|
request.SendStatus(200, "OK");
|
||
|
request.SendHeader("Content-type", "text/html");
|
||
|
request.SendBodyData(RedmondSBCMapPage.HTMLData);
|
||
|
}
|
||
|
else if (request.GetUriPath().EndsWith("redmond_tullys.htm")) {
|
||
|
request.SendStatus(200, "OK");
|
||
|
request.SendHeader("Content-type", "text/html");
|
||
|
request.SendBodyData(RedmondTullysMapPage.HTMLData);
|
||
|
}
|
||
|
// Pages added for the Virtual Earth demo
|
||
|
else if (request.GetUriPath().IndexOf("ve1.aspx") != -1) {
|
||
|
request.SendStatus(200, "OK");
|
||
|
request.SendHeader("Content-type", "text/html");
|
||
|
//byte [] htmlBytes = ProcessAspx(VePage1.HTMLData, request);
|
||
|
//request.SendBodyData(htmlBytes);
|
||
|
request.SendBodyData(VePage1.HTMLData);
|
||
|
}
|
||
|
else if (request.GetUriPath().IndexOf("ve2.aspx") != -1) {
|
||
|
request.SendStatus(200, "OK");
|
||
|
request.SendHeader("Content-type", "text/html");
|
||
|
byte [] htmlBytes = ProcessAspx(VePage2.HTMLData, request);
|
||
|
request.SendBodyData(htmlBytes);
|
||
|
}
|
||
|
else if (request.GetUriPath().IndexOf("ve3.aspx") != -1) {
|
||
|
request.SendStatus(200, "OK");
|
||
|
request.SendHeader("Content-type", "text/html");
|
||
|
byte [] htmlBytes = ProcessAspx(VePage3.HTMLData, request);
|
||
|
request.SendBodyData(htmlBytes);
|
||
|
}
|
||
|
else if (request.GetUriPath().IndexOf("ve.aspx") != -1) {
|
||
|
request.SendStatus(200, "OK");
|
||
|
request.SendHeader("Content-type", "text/html");
|
||
|
byte [] htmlBytes = ProcessAspx(VePage.HTMLData, request);
|
||
|
request.SendBodyData(htmlBytes);
|
||
|
}
|
||
|
else if (request.GetUriPath().IndexOf("LocalSearch.js") != -1) {
|
||
|
request.SendStatus(200, "OK");
|
||
|
request.SendHeader("Content-type", "text/javascript");
|
||
|
byte [] htmlBytes = IssueLocalSearch(ExtractQueryParamValue("loc", request.GetQueryString()), ExtractQueryParamValue("search", request.GetQueryString()));
|
||
|
request.SendBodyData(htmlBytes);
|
||
|
}
|
||
|
else if (request.GetUriPath().IndexOf("Traffic.js") != -1) {
|
||
|
request.SendStatus(200, "OK");
|
||
|
request.SendHeader("Content-type", "text/javascript");
|
||
|
byte [] htmlBytes = IssueTrafficQuery();
|
||
|
request.SendBodyData(htmlBytes);
|
||
|
}
|
||
|
else if (request.GetUriPath().EndsWith("MapControl.js")) {
|
||
|
DebugStub.Break();
|
||
|
}
|
||
|
else {
|
||
|
// serve main page for lack of any better ideas
|
||
|
request.SendStatus(200, "OK");
|
||
|
request.SendHeader("Content-type", "text/html");
|
||
|
request.SendBodyData(MainMapPage.HTMLData);
|
||
|
}
|
||
|
}
|
||
|
finally {
|
||
|
m_MapConn.Release(impMapConn);
|
||
|
}
|
||
|
|
||
|
request.Done();
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// HACK: Search and replace specific ASPX strings. (And slowly!)
|
||
|
// This isn't even the beginnings of real ASPX support.
|
||
|
//
|
||
|
private byte []! ProcessAspx(byte []! aspxBytes, IHttpRequest! request)
|
||
|
{
|
||
|
string s = Encoding.UTF8.GetString(aspxBytes);
|
||
|
s = s.Replace("<%=Request.QueryString(\"loc\")%>", ExtractQueryParamValue("loc", request.GetQueryString()));
|
||
|
s = s.Replace("<%=Request.QueryString(\"search\")%>", ExtractQueryParamValue("search", request.GetQueryString()));
|
||
|
byte [] htmlBytes = Encoding.UTF8.GetBytes(s);
|
||
|
return htmlBytes;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// HACK: Simple extraction of query param value. Doesn't handle encoding.
|
||
|
// This should be replaced when there are better helper functions or regular expressions.
|
||
|
//
|
||
|
private string ExtractQueryParamValue(string! paramName, string queryString)
|
||
|
{
|
||
|
if (queryString == null) {
|
||
|
return "";
|
||
|
}
|
||
|
|
||
|
int start = queryString.IndexOf(paramName + "=");
|
||
|
if (start == -1) {
|
||
|
return "";
|
||
|
}
|
||
|
start += paramName.Length + 1;
|
||
|
int end = queryString.IndexOf("&", start);
|
||
|
if (end == -1) {
|
||
|
return queryString.Substring(start);
|
||
|
}
|
||
|
else {
|
||
|
return queryString.Substring(start, end - start);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// HACK: This should be a call to MSN Local Search followed by parsing of the XML results.
|
||
|
// Instead we'll use the pre-cached search results until we have a richer XML parser.
|
||
|
//
|
||
|
private byte []! IssueLocalSearch(string loc, string search)
|
||
|
{
|
||
|
PushPinData [] pushPins = SeattlePushPins;
|
||
|
if (loc == "redmond") {
|
||
|
pushPins = RedmondPushPins;
|
||
|
}
|
||
|
|
||
|
byte searchMask = 3;
|
||
|
if (search == "starbucks") {
|
||
|
searchMask = 1;
|
||
|
}
|
||
|
else if (search == "tullys") {
|
||
|
searchMask = 2;
|
||
|
}
|
||
|
|
||
|
// Build the javascript result
|
||
|
string s = "function AddSearchResultsPushpins(map){\r\n";
|
||
|
for (int i = 0; i < pushPins.Length; i++) {
|
||
|
if ((pushPins[i].groupMask & searchMask) != 0) {
|
||
|
string sBmp = "green.bmp";
|
||
|
if ((pushPins[i].groupMask & 0x2) != 0) {
|
||
|
sBmp = "red.bmp";
|
||
|
}
|
||
|
string tmp = String.Format("map.AddPushpin('ls{0}', {1}, {2}, 0, 0, 'pinIcon', '<img src=\"{3}\">', {4});\r\n",
|
||
|
i, pushPins[i].latitude, pushPins[i].longitude, sBmp,
|
||
|
i + 1);
|
||
|
s += tmp;
|
||
|
}
|
||
|
}
|
||
|
s += "}";
|
||
|
byte [] htmlBytes = Encoding.UTF8.GetBytes(s);
|
||
|
return htmlBytes;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// IssueTrafficQuery - Calls out to the SeattleTrafficProxy service to find
|
||
|
// current traffic data. Maps the data into jscript for the virtual earth
|
||
|
// client to use.
|
||
|
//
|
||
|
private byte []! IssueTrafficQuery()
|
||
|
{
|
||
|
// Bind to the traffic service over a channel
|
||
|
SeattleTrafficProxyContract.Imp imp = BindToTrafficChannel();
|
||
|
if (imp == null) {
|
||
|
// Return empty jscript on error
|
||
|
string s = "function AddTrafficResultsPushpins(map){}";
|
||
|
return Encoding.UTF8.GetBytes(s);
|
||
|
}
|
||
|
|
||
|
// Fetch the traffic data
|
||
|
TrafficInfo []! in ExHeap trafficInfo;
|
||
|
imp.SendGetTraffic();
|
||
|
imp.RecvTraffic(out trafficInfo);
|
||
|
|
||
|
// Close the channel
|
||
|
delete imp;
|
||
|
|
||
|
// Build the jscript from the traffic data
|
||
|
string js = "function AddTrafficResultsPushpins(map){\r\n";
|
||
|
for (int i = 0; i < trafficInfo.Length; i++) {
|
||
|
if (trafficInfo[i].minUntilFree < 2)
|
||
|
continue;
|
||
|
string textStyle = "pinGreen";
|
||
|
if (trafficInfo[i].minUntilFree > 10) {
|
||
|
textStyle = "pinRed";
|
||
|
}
|
||
|
string jsLine = String.Format("map.AddPushpin('t{0}', {1}, {2}, 0, 0, '{3}', '{4} Min', {5});\r\n",
|
||
|
i, trafficInfo[i].latitude, trafficInfo[i].longitude, textStyle, trafficInfo[i].minUntilFree, i + 1);
|
||
|
js += jsLine;
|
||
|
}
|
||
|
js += "}";
|
||
|
|
||
|
// REVIEW: manually release the traffic data in the exchange heap
|
||
|
delete trafficInfo;
|
||
|
return Encoding.UTF8.GetBytes(js);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// BindToTrafficChannel - Helper function to establish the channel.
|
||
|
//
|
||
|
private SeattleTrafficProxyContract.Imp:ReadyState BindToTrafficChannel()
|
||
|
{
|
||
|
SeattleTrafficProxyContract.Exp! exp;
|
||
|
SeattleTrafficProxyContract.Imp! imp;
|
||
|
SeattleTrafficProxyContract.NewChannel(out imp, out exp);
|
||
|
|
||
|
// Get the namespace endpoint
|
||
|
DirectoryServiceContract.Imp ns = DirectoryService.NewClientEndpoint();
|
||
|
try {
|
||
|
ns.SendBind(Bitter.FromString2(SeattleTrafficProxyContract.ModuleName), exp);
|
||
|
switch receive {
|
||
|
case ns.AckBind():
|
||
|
imp.RecvReady();
|
||
|
break;
|
||
|
case ns.NakBind(rejected, error):
|
||
|
delete imp;
|
||
|
delete rejected;
|
||
|
Console.WriteLine("Received NakLookup from namespace.");
|
||
|
return null;
|
||
|
case ns.ChannelClosed():
|
||
|
Console.WriteLine("Channel closed to nameserver.");
|
||
|
delete imp;
|
||
|
return null;
|
||
|
}
|
||
|
}
|
||
|
finally {
|
||
|
delete ns;
|
||
|
}
|
||
|
return imp;
|
||
|
}
|
||
|
|
||
|
private void ServeMap(IHttpRequest! request, MapPointProxyContract.Imp:ReadyState! impMapConn,
|
||
|
[Claims]char[]! in ExHeap centerLat, [Claims]char[]! in ExHeap centerLong,
|
||
|
int zoom, [Claims]MapPointProxyContract.PushPin[]! in ExHeap pushPins)
|
||
|
{
|
||
|
impMapConn.SendGetMap(centerLat, centerLong, zoom, pushPins);
|
||
|
|
||
|
request.SendStatus(200, "OK");
|
||
|
|
||
|
switch receive {
|
||
|
case impMapConn.Failed() :
|
||
|
{
|
||
|
request.SendHeader("Content-type", "text/plain");
|
||
|
request.SendBodyData(Encoding.ASCII.GetBytes("Failed"));
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case impMapConn.MapDataBegin() :
|
||
|
{
|
||
|
request.SendHeader("Content-type", "image/gif");
|
||
|
bool done = false;
|
||
|
|
||
|
while (!done) {
|
||
|
switch receive {
|
||
|
case impMapConn.MapDataChunk(byte[]! in ExHeap dataChunk) :
|
||
|
{
|
||
|
request.SendBodyData(Bitter.ToByteArray(dataChunk));
|
||
|
impMapConn.SendAck();
|
||
|
delete dataChunk;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case impMapConn.Done() :
|
||
|
{
|
||
|
done = true;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case impMapConn.ChannelClosed() :
|
||
|
throw new Exception("impMapConn channel closed");
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
case impMapConn.ChannelClosed() :
|
||
|
throw new Exception("impMapConn channel closed");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void SetLatitude(ref MapPointProxyContract.PushPin pushPin, string! latitude)
|
||
|
{
|
||
|
expose(pushPin)
|
||
|
{
|
||
|
char[] in ExHeap tmp = pushPin.latitude;
|
||
|
|
||
|
if (tmp != null) {
|
||
|
delete tmp;
|
||
|
}
|
||
|
|
||
|
pushPin.latitude = Bitter.FromString2(latitude);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void SetLongitude(ref MapPointProxyContract.PushPin pushPin, string! longitude)
|
||
|
{
|
||
|
expose(pushPin)
|
||
|
{
|
||
|
char[] in ExHeap tmp = pushPin.longitude;
|
||
|
|
||
|
if (tmp != null) {
|
||
|
delete tmp;
|
||
|
}
|
||
|
|
||
|
pushPin.longitude = Bitter.FromString2(longitude);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void SetIcon(ref MapPointProxyContract.PushPin pushPin, string! icon)
|
||
|
{
|
||
|
expose(pushPin)
|
||
|
{
|
||
|
char[] in ExHeap tmp = pushPin.icon;
|
||
|
|
||
|
if (tmp != null) {
|
||
|
delete tmp;
|
||
|
}
|
||
|
|
||
|
pushPin.icon = Bitter.FromString2(icon);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void SetLabel(ref MapPointProxyContract.PushPin pushPin, string! label)
|
||
|
{
|
||
|
expose(pushPin)
|
||
|
{
|
||
|
char[] in ExHeap tmp = pushPin.label;
|
||
|
|
||
|
if (tmp != null) {
|
||
|
delete tmp;
|
||
|
}
|
||
|
|
||
|
pushPin.label = Bitter.FromString2(label);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private MapPointProxyContract.PushPin[]! in ExHeap BuildPushPins(PushPinData[]! pinData, byte mask)
|
||
|
{
|
||
|
// Make one pass to figure out how many we will use
|
||
|
int numPins = 0;
|
||
|
|
||
|
for (int i = 0; i < pinData.Length; ++i) {
|
||
|
if ((pinData[i].groupMask == 0) || ((pinData[i].groupMask & mask) != 0)) {
|
||
|
numPins++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int outputIndex = 0;
|
||
|
MapPointProxyContract.PushPin[]! in ExHeap pushPins = new[ExHeap] MapPointProxyContract.PushPin[numPins];
|
||
|
|
||
|
for (int i = 0; i < pinData.Length; ++i) {
|
||
|
if ((pinData[i].groupMask == 0) || ((pinData[i].groupMask & mask) != 0)) {
|
||
|
CustomVector.Expose(pushPins, outputIndex);
|
||
|
pushPins[outputIndex].UnExpose();
|
||
|
SetLatitude(ref pushPins[outputIndex], pinData[i].latitude);
|
||
|
SetLongitude(ref pushPins[outputIndex], pinData[i].longitude);
|
||
|
SetIcon(ref pushPins[outputIndex], pinData[i].icon);
|
||
|
|
||
|
if (pinData[i].label != null) {
|
||
|
SetLabel(ref pushPins[outputIndex], pinData[i].label);
|
||
|
}
|
||
|
|
||
|
pushPins[outputIndex].Expose();
|
||
|
CustomVector.UnExpose(pushPins, outputIndex);
|
||
|
outputIndex++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return pushPins;
|
||
|
}
|
||
|
|
||
|
private struct PushPinData
|
||
|
{
|
||
|
public string! latitude;
|
||
|
public string! longitude;
|
||
|
public string! icon;
|
||
|
public string label;
|
||
|
public byte groupMask;
|
||
|
|
||
|
public PushPinData(string! latit, string! longi, string! ic,
|
||
|
string lab, byte mask)
|
||
|
{
|
||
|
latitude = latit;
|
||
|
longitude = longi;
|
||
|
icon = ic;
|
||
|
label = lab;
|
||
|
groupMask = mask;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private static readonly PushPinData[] RedmondPushPins = {
|
||
|
// "You are here"
|
||
|
new PushPinData("47.641372008066419", "-122.14171843658843", "42" /*office building*/, "You are here (Microsoft Research)", 0),
|
||
|
// Starbucks
|
||
|
|
||
|
|
||
|
new PushPinData("47.617380881124", "-122.204285557882", "DriveThruIcon" /*green coffee circle*/, null, 1),
|
||
|
new PushPinData("47.6105671286853", "-122.201565707188", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.604523", "-122.20153", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.615745", "-122.198709", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6126613078903", "-122.196318968814", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6146420627496", "-122.196305308435", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6155317081101", "-122.196324288713", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6166209390934", "-122.180393700239", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6811084016238", "-122.125467537411", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6744181996394", "-122.129225665666", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6742935198659", "-122.129642662136", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.671387274374", "-122.113099943966", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6706035", "-122.121555", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6709643825666", "-122.11139397589", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6711687083206", "-122.106119490634", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.7047004699707", "-122.133796691895", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.7023416916925", "-122.092923565158", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6793076942739", "-122.173964223732", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6792316094164", "-122.178085721598", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.7111056625465", "-122.189069067129", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6782272996955", "-122.200388198634", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6662864685059", "-122.196502685547", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6315532907175", "-122.140098558258", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.7000740688881", "-122.026042352805", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.7072906494141", "-122.211235046387", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.7521", "-122.1061", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6249966295313", "-122.153698588393", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6569587329949", "-122.206521525077", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.72324", "-122.20725", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.617137", "-122.132195", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6169609119728", "-122.132415718939", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.7544271700597"," 122.154070188864", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.7544287143031", "-122.155023645092", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.7552703980699", "-122.08142692402", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6097464987024", "-122.139934976989", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.7593566957892", "-122.174967797468", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6145387545187", "-122.035404694481", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.612365467811", "-122.035490975435", "DriveThruIcon", null, 1),
|
||
|
// Tullys
|
||
|
new PushPinData("47.6810758977117", "-122.12546258636381", "CoffeeShopIcon" /*Red coffee circle*/, null, 2),
|
||
|
new PushPinData("47.671001368685936", "-122.04650559955846", "CoffeeShopIcon", null, 2),
|
||
|
// SBC
|
||
|
new PushPinData("47.670178330890948", "-122.11961594443427", "KioskIcon" /*Blue coffee circle*/, null, 4),
|
||
|
new PushPinData("47.608457326456126", "-122.20149625220438", "KioskIcon", null, 4),
|
||
|
new PushPinData("47.574152701349739", "-122.17140243872132", "KioskIcon", null, 4)
|
||
|
};
|
||
|
|
||
|
private static readonly PushPinData[] SeattlePushPins = {
|
||
|
// "You are here"
|
||
|
new PushPinData("47.614037591008028", "-122.30879852406528", "27" /*house with flag*/, "You are here (home)", 0),
|
||
|
// Starbucks
|
||
|
new PushPinData("47.618456723401", "-122.303580259539", "DriveThruIcon" /*green coffee circle*/, null, 1),
|
||
|
new PushPinData("47.6091994192007", "-122.31668636661", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6199422895455", "-122.313743581024", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.599437", "-122.301895", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6212111570895", "-122.312649269183", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6128901192275", "-122.320724034356", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6018627788125", "-122.285193390294", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.610237862022", "-122.322928315481", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6092905987202", "-122.325162208694", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6221450255528", "-122.32086063814", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6223663747617", "-122.320829450141", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6188045355887", "-122.325239193537", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6162334968262", "-122.329890148222", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6169046494928", "-122.330289641677", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6043728733325", "-122.329780865196", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6043721971621", "-122.329784402156", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6108171568144", "-122.331843582325", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6090423881785", "-122.332809531195", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6117170454482", "-122.333517921376", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6069301134782", "-122.333694075029", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.598136", "-122.327903", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6098478103493", "-122.334743355756", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6131155154701", "-122.334862525938", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6055032696401", "-122.333919959833", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6055017170637", "-122.3339229573", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6020524524996", "-122.332223568544", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6084345306019", "-122.335046964734", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.612046590865", "-122.335381620315", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.606388128686", "-122.334715667519", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6116967823789", "-122.336296136407", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6051471566206", "-122.335104086031", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6101314840046", "-122.336650815449", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.60168", "-122.333949", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6064691727839", "-122.336272716656", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6135660835676", "-122.336924441826", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6033756657136", "-122.335026450478", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6112337983537", "-122.337417016688", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6112337983537", "-122.337417016688", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6072289673078", "-122.337106017343", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.599135190386", "-122.332838828233", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6093179302915", "-122.33863279036", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6333928948529", "-122.281512273042", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6044616657917", "-122.339138224358", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.61381560986", "-122.341310224515", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6097464987024", "-122.342189276209", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6125529038982", "-122.342905420618", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6184752170526", "-122.344648806947", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6135154241179", "-122.346735619683", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6107420247335", "-122.347675960821", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6220015915803", "-122.345818149367", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6298972902608", "-122.340996035813", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6299348563012", "-122.342293771755", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.622011836864", "-122.348399960873", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6408255929328", "-122.32587399699", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.5855659474528", "-122.334138525886", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.5773975925697", "-122.296242307054", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.5817820226526", "-122.335067431613", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6236038208008", "-122.355293273926", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.622346107565", "-122.356638643795", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.5693792904357", "-122.290340867944", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.637629805258", "-122.35698045001", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6575288205481", "-122.313210826269", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6497241214904", "-122.349778323383", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6622877389576", "-122.31307855344", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6642975380156", "-122.301667806572", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.559056", "-122.285462", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6613800962745", "-122.333579501002", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6664012362799", "-122.299577768686", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.5811287489603", "-122.383682139035", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6484821201053", "-122.37802019047", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.5483623833267", "-122.321082626329", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6750775445954", "-122.317375978787", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.5807287886721", "-122.386386715489", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.660603", "-122.370295", "DriveThruIcon", null, 1),
|
||
|
new PushPinData("47.6798149294931", "-122.325708188256", "DriveThruIcon", null, 1),
|
||
|
// Tullys
|
||
|
new PushPinData("47.556308832143081", "-122.14664983316918", "137", null, 6),
|
||
|
new PushPinData("47.626021157906813", "-122.30730954282622", "CoffeeShopIcon", null, 2),
|
||
|
new PushPinData("47.607811873579557", "-122.33913822435848", "CoffeeShopIcon", null, 2),
|
||
|
new PushPinData("47.556308832143081", "-122.14664983316918", "CoffeeShopIcon", null, 2),
|
||
|
new PushPinData("47.617097515756193", "-122.35281226307684", "CoffeeShopIcon", null, 2),
|
||
|
new PushPinData("47.605650118707253", "-122.33404290323766", "CoffeeShopIcon", null, 2),
|
||
|
new PushPinData("47.60911643971103", "-122.33572312977347", "137", null, 6),
|
||
|
new PushPinData("47.608771515157947", "-122.34009445084229", "137", null, 6),
|
||
|
new PushPinData("47.599181929563251", "-122.33139278983968", "137", null, 6),
|
||
|
new PushPinData("47.633845139601064", "-122.28094501262997", "CoffeeShopIcon", null, 2),
|
||
|
new PushPinData("47.556308832143081", "-122.14664983316918", "137", null, 6),
|
||
|
new PushPinData("47.610117062424443", "-122.33346916734737", "CoffeeShopIcon", null, 2),
|
||
|
new PushPinData("47.611677760649791", "-122.33647445058217", "CoffeeShopIcon", null, 2),
|
||
|
// SBC
|
||
|
new PushPinData("47.610117062424443", "-122.33655641285222", "KioskIcon", /*Blue coffee circle*/ null, 4),
|
||
|
new PushPinData("47.60678051501489", "-122.33355112961741", "KioskIcon", null, 8),
|
||
|
new PushPinData("47.602412609040663", "-122.33254026162025", "KioskIcon", null, 8),
|
||
|
new PushPinData("47.608826156671306", "-122.33998516781557", "KioskIcon", null, 8),
|
||
|
new PushPinData("47.556308832143081", "-122.14664983316918", "KioskIcon", null, 8)
|
||
|
};
|
||
|
|
||
|
// ======================================================
|
||
|
// The code below gets used when this webapp is compiled
|
||
|
// to a stand-alone executable
|
||
|
internal static int AppMain(Parameters! config)
|
||
|
{
|
||
|
//Endpoint * in ExHeap ep = Process.GetStartupEndpoint(0);
|
||
|
WebAppContract.Exp conn = config.webAppRef.Acquire();
|
||
|
if (conn == null) {
|
||
|
// Wrong contract type!
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
conn.SendWebAppReady();
|
||
|
MapDemoWebApp webApp = new MapDemoWebApp();
|
||
|
Driver.ServiceChannel(webApp, conn);
|
||
|
delete conn;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
private void ReportInternalError(IHttpRequest! request, string! description)
|
||
|
{
|
||
|
request.SendStatus(500, "Internal Error");
|
||
|
request.SendHeader("Content-type", "text/plain");
|
||
|
request.SendHeader("charset", "utf-8");
|
||
|
request.SendBodyData(Encoding.ASCII.GetBytes(description));
|
||
|
}
|
||
|
|
||
|
}
|
||
|
}
|