2021-03-30 17:15:16 +08:00
|
|
|
|
using Assets.Scenes.Ride.Scripts.Model;
|
2021-04-22 19:29:59 +08:00
|
|
|
|
using Assets.Scripts;
|
|
|
|
|
|
using Assets.Scripts.Apis.Models;
|
2021-03-30 17:15:16 +08:00
|
|
|
|
using System;
|
2021-04-22 19:29:59 +08:00
|
|
|
|
using System.Text;
|
2021-03-28 18:17:15 +08:00
|
|
|
|
using System.Collections.Generic;
|
2021-03-23 16:07:31 +08:00
|
|
|
|
using System.Globalization;
|
2021-03-28 18:17:15 +08:00
|
|
|
|
using System.IO;
|
2021-03-30 17:15:16 +08:00
|
|
|
|
using System.Linq;
|
2021-04-22 19:29:59 +08:00
|
|
|
|
using System.Net.Http;
|
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
|
using UnityEngine;
|
|
|
|
|
|
using UnityEngine.Networking;
|
2021-03-23 16:07:31 +08:00
|
|
|
|
|
|
|
|
|
|
namespace Assets.Scenes.Ride.Scripts
|
|
|
|
|
|
{
|
|
|
|
|
|
public class Helper
|
|
|
|
|
|
{
|
2021-05-10 18:13:27 +08:00
|
|
|
|
public static string CreateDirectoryIfNotExsit(string path)
|
2021-03-28 18:17:15 +08:00
|
|
|
|
{
|
2021-05-10 18:13:27 +08:00
|
|
|
|
if (!Directory.Exists(path))
|
2021-04-28 17:23:29 +08:00
|
|
|
|
{
|
2021-05-10 18:13:27 +08:00
|
|
|
|
Directory.CreateDirectory(path);
|
2021-04-28 17:23:29 +08:00
|
|
|
|
}
|
2021-05-10 18:13:27 +08:00
|
|
|
|
return path;
|
2021-03-30 17:15:16 +08:00
|
|
|
|
}
|
2021-04-29 18:07:30 +08:00
|
|
|
|
|
|
|
|
|
|
public static void DelectDir(string srcPath)
|
|
|
|
|
|
{
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
2021-05-20 15:55:27 +08:00
|
|
|
|
if (!Directory.Exists(srcPath))
|
|
|
|
|
|
return;
|
2021-04-29 18:07:30 +08:00
|
|
|
|
DirectoryInfo dir = new DirectoryInfo(srcPath);
|
|
|
|
|
|
FileSystemInfo[] fileinfo = dir.GetFileSystemInfos(); //返回目录中所有文件和子目录
|
|
|
|
|
|
foreach (FileSystemInfo i in fileinfo)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (i is DirectoryInfo) //判断是否文件夹
|
|
|
|
|
|
{
|
|
|
|
|
|
DirectoryInfo subdir = new DirectoryInfo(i.FullName);
|
|
|
|
|
|
subdir.Delete(true); //删除子目录和文件
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
File.Delete(i.FullName); //删除指定文件
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
//删除当前文件夹
|
|
|
|
|
|
Directory.Delete(srcPath);
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
|
{
|
|
|
|
|
|
throw;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2021-03-30 17:15:16 +08:00
|
|
|
|
public static double AveragePower(IList<TargetData> list)
|
|
|
|
|
|
{
|
|
|
|
|
|
return Math.Floor(list.Where(p => p._Power > -1).Average(a => a._Power));
|
|
|
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 优化功率
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="list"></param>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
public static double GetNP(List<TargetData> list)
|
|
|
|
|
|
{
|
|
|
|
|
|
var _npinterval = new List<double>();
|
|
|
|
|
|
var count = list.Count / 28;
|
|
|
|
|
|
for (int i = 0; i < count; i++)
|
2021-03-28 18:17:15 +08:00
|
|
|
|
{
|
2021-03-30 17:15:16 +08:00
|
|
|
|
var list1 = list.Skip(i * 28).Take(28);
|
|
|
|
|
|
double avgpower = Math.Pow((int)list1.Where(d => d._Power > -1).Average(a => a._Power), 4);
|
|
|
|
|
|
_npinterval.Add(avgpower);
|
2021-03-28 18:17:15 +08:00
|
|
|
|
}
|
2021-03-30 17:15:16 +08:00
|
|
|
|
double n = 0.25;
|
|
|
|
|
|
if (_npinterval.Count == 0) return 0;
|
|
|
|
|
|
return Math.Pow((_npinterval.Sum() / _npinterval.Count), n);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2021-04-30 17:25:28 +08:00
|
|
|
|
/// 获取Ftp
|
2021-03-30 17:15:16 +08:00
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
public static int GetFtp()
|
|
|
|
|
|
{
|
2021-04-30 17:25:28 +08:00
|
|
|
|
return App.CurrentUser.FTP;
|
2021-03-28 18:17:15 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2021-03-25 16:22:09 +08:00
|
|
|
|
public static string FormatTicks(int seconds)
|
|
|
|
|
|
{
|
|
|
|
|
|
int h, m, s;
|
|
|
|
|
|
h = seconds / 3600;
|
|
|
|
|
|
m = (seconds - (3600 * h)) / 60;
|
|
|
|
|
|
s = seconds - (3600 * h + 60 * m);
|
|
|
|
|
|
string H, M, S;
|
|
|
|
|
|
H = M = S = string.Empty;
|
|
|
|
|
|
if (h < 10)
|
|
|
|
|
|
H = "0" + h;
|
|
|
|
|
|
else
|
|
|
|
|
|
H = h.ToString();
|
|
|
|
|
|
if (m < 10)
|
|
|
|
|
|
M = "0" + m;
|
|
|
|
|
|
else
|
|
|
|
|
|
M = m.ToString();
|
|
|
|
|
|
if (s < 10)
|
|
|
|
|
|
S = "0" + s;
|
|
|
|
|
|
else
|
|
|
|
|
|
S = s.ToString();
|
|
|
|
|
|
return $"{H}:{M}:{S}";
|
|
|
|
|
|
}
|
2021-03-23 16:07:31 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 计算速度
|
|
|
|
|
|
/// 参考 http://bikecalculator.com/index.html
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="elevationv">海拔</param>
|
|
|
|
|
|
/// <param name="gradev">坡度%</param>
|
|
|
|
|
|
/// <param name="powerv">功率</param>
|
|
|
|
|
|
/// <param name="rweightv">体重</param>
|
|
|
|
|
|
/// <param name="bweightv">自行车重量</param>
|
|
|
|
|
|
/// <returns>km/h</returns>
|
|
|
|
|
|
public static double CalculateSpeed(double elevationv, double gradev, double powerv, double rweightv, double bweightv)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (powerv < 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (gradev < -10)
|
|
|
|
|
|
{
|
|
|
|
|
|
gradev = -10;
|
|
|
|
|
|
}
|
|
|
|
|
|
var tireValues = new double[] { 0.005, 0.004, 0.012 };
|
|
|
|
|
|
var aeroValues = new double[] { 0.388, 0.445, 0.420, 0.300, 0.233, 0.200 };
|
|
|
|
|
|
var units = 0;
|
|
|
|
|
|
|
|
|
|
|
|
//温度
|
|
|
|
|
|
var temperaturev = 25;
|
|
|
|
|
|
|
|
|
|
|
|
//海拔
|
|
|
|
|
|
//var elevationv = 100;
|
|
|
|
|
|
|
|
|
|
|
|
//坡度
|
|
|
|
|
|
//var gradev = 6 * 0.01 * -1;
|
|
|
|
|
|
|
|
|
|
|
|
//风,转换成m/s
|
|
|
|
|
|
var headwindv = 0 / 3.6;
|
|
|
|
|
|
|
|
|
|
|
|
var frontalArea = aeroValues[0];
|
|
|
|
|
|
|
|
|
|
|
|
var transv = 0.95; // no one knows what this is, so why bother presenting a choice?
|
|
|
|
|
|
var rollingRes = tireValues[0];
|
|
|
|
|
|
|
|
|
|
|
|
//应该是空气密度
|
|
|
|
|
|
var density = (1.293 - 0.00426 * temperaturev) * Math.Exp(-elevationv / 7000.0);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//全空气阻力参数
|
|
|
|
|
|
var a2 = 0.5 * frontalArea * density; // full air resistance parameter
|
|
|
|
|
|
var twt = 9.8 * (rweightv + bweightv); // total weight in newtons
|
|
|
|
|
|
var tres = twt * (gradev * 0.01 + rollingRes); // gravity and rolling resistance
|
|
|
|
|
|
|
|
|
|
|
|
//var powerv = 195;
|
|
|
|
|
|
|
|
|
|
|
|
var v = Newton(a2, headwindv, tres, transv, powerv) * 3.6;// convert to km/h
|
|
|
|
|
|
|
|
|
|
|
|
//Trace.WriteLine($"速度为:{ v }");
|
|
|
|
|
|
|
|
|
|
|
|
var t1 = makeDecimal2(v * (units == 1 ? 1.609 : 1.0));
|
|
|
|
|
|
return double.Parse(t1, CultureInfo.InvariantCulture);
|
|
|
|
|
|
}
|
|
|
|
|
|
private static double Newton(double aero, double hw, double tr, double tran, double p)
|
|
|
|
|
|
{
|
|
|
|
|
|
var vel = 20D;
|
|
|
|
|
|
var MAX = 10;
|
|
|
|
|
|
var TOL = 0.05;
|
|
|
|
|
|
for (int i = 0; i < MAX; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
var tv = vel + hw;
|
|
|
|
|
|
var aeroEff = (tv > 0.0) ? aero : -aero; // wind in face, must reverse effect
|
|
|
|
|
|
var f = vel * (aeroEff * tv * tv + tr) - tran * p; // the function
|
|
|
|
|
|
var fp = aeroEff * (3.0 * vel + hw) * tv + tr; // the derivative
|
|
|
|
|
|
var vNew = vel - f / fp;
|
|
|
|
|
|
if (Math.Abs(vNew - vel) < TOL)
|
|
|
|
|
|
{
|
|
|
|
|
|
return vNew; // success
|
|
|
|
|
|
}
|
|
|
|
|
|
vel = vNew;
|
|
|
|
|
|
}
|
|
|
|
|
|
return 0.0;
|
|
|
|
|
|
}
|
|
|
|
|
|
private static string makeDecimal2(double value)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (value != 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
var x = Math.Round(value * 100);
|
|
|
|
|
|
int d;
|
|
|
|
|
|
if (x < 100)
|
|
|
|
|
|
{
|
|
|
|
|
|
d = 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
d = Convert.ToInt32(Math.Floor(x / 100), CultureInfo.InvariantCulture);
|
|
|
|
|
|
};
|
|
|
|
|
|
var c = x % 100;
|
|
|
|
|
|
var g = (c >= 10) ? "" : "0";
|
|
|
|
|
|
return "" + d + "." + g + c;
|
|
|
|
|
|
}
|
|
|
|
|
|
return value.ToString(CultureInfo.InvariantCulture);
|
|
|
|
|
|
}
|
2021-04-22 19:29:59 +08:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Decode google style polyline coordinates.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="encodedPoints"></param>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
private static IEnumerable<CoordinateEntity> Decode(string encodedPoints)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (string.IsNullOrEmpty(encodedPoints))
|
|
|
|
|
|
throw new ArgumentNullException("encodedPoints");
|
|
|
|
|
|
|
|
|
|
|
|
char[] polylineChars = encodedPoints.ToCharArray();
|
|
|
|
|
|
int index = 0;
|
|
|
|
|
|
|
|
|
|
|
|
int currentLat = 0;
|
|
|
|
|
|
int currentLng = 0;
|
|
|
|
|
|
int next5bits;
|
|
|
|
|
|
int sum;
|
|
|
|
|
|
int shifter;
|
|
|
|
|
|
|
|
|
|
|
|
while (index < polylineChars.Length)
|
|
|
|
|
|
{
|
|
|
|
|
|
// calculate next latitude
|
|
|
|
|
|
sum = 0;
|
|
|
|
|
|
shifter = 0;
|
|
|
|
|
|
do
|
|
|
|
|
|
{
|
|
|
|
|
|
next5bits = (int)polylineChars[index++] - 63;
|
|
|
|
|
|
sum |= (next5bits & 31) << shifter;
|
|
|
|
|
|
shifter += 5;
|
|
|
|
|
|
} while (next5bits >= 32 && index < polylineChars.Length);
|
|
|
|
|
|
|
|
|
|
|
|
if (index >= polylineChars.Length)
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
currentLat += (sum & 1) == 1 ? ~(sum >> 1) : (sum >> 1);
|
|
|
|
|
|
|
|
|
|
|
|
//calculate next longitude
|
|
|
|
|
|
sum = 0;
|
|
|
|
|
|
shifter = 0;
|
|
|
|
|
|
do
|
|
|
|
|
|
{
|
|
|
|
|
|
next5bits = (int)polylineChars[index++] - 63;
|
|
|
|
|
|
sum |= (next5bits & 31) << shifter;
|
|
|
|
|
|
shifter += 5;
|
|
|
|
|
|
} while (next5bits >= 32 && index < polylineChars.Length);
|
|
|
|
|
|
|
|
|
|
|
|
if (index >= polylineChars.Length && next5bits >= 32)
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
currentLng += (sum & 1) == 1 ? ~(sum >> 1) : (sum >> 1);
|
|
|
|
|
|
|
|
|
|
|
|
yield return new CoordinateEntity
|
|
|
|
|
|
{
|
|
|
|
|
|
Latitude = Convert.ToDouble(currentLat) / 1E5,
|
|
|
|
|
|
Longitude = Convert.ToDouble(currentLng) / 1E5
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Encode it
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="points"></param>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
private static string Encode(IEnumerable<CoordinateEntity> points)
|
|
|
|
|
|
{
|
|
|
|
|
|
var str = new StringBuilder();
|
|
|
|
|
|
|
|
|
|
|
|
var encodeDiff = (Action<int>)(diff =>
|
|
|
|
|
|
{
|
|
|
|
|
|
int shifted = diff << 1;
|
|
|
|
|
|
if (diff < 0)
|
|
|
|
|
|
shifted = ~shifted;
|
|
|
|
|
|
|
|
|
|
|
|
int rem = shifted;
|
|
|
|
|
|
|
|
|
|
|
|
while (rem >= 0x20)
|
|
|
|
|
|
{
|
|
|
|
|
|
str.Append((char)((0x20 | (rem & 0x1f)) + 63));
|
|
|
|
|
|
|
|
|
|
|
|
rem >>= 5;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
str.Append((char)(rem + 63));
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
int lastLat = 0;
|
|
|
|
|
|
int lastLng = 0;
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var point in points)
|
|
|
|
|
|
{
|
|
|
|
|
|
int lat = (int)Math.Round(point.Latitude * 1E5);
|
|
|
|
|
|
int lng = (int)Math.Round(point.Longitude * 1E5);
|
|
|
|
|
|
|
|
|
|
|
|
encodeDiff(lat - lastLat);
|
|
|
|
|
|
encodeDiff(lng - lastLng);
|
|
|
|
|
|
|
|
|
|
|
|
lastLat = lat;
|
|
|
|
|
|
lastLng = lng;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return str.ToString();
|
|
|
|
|
|
}
|
|
|
|
|
|
public struct CoordinateEntity
|
|
|
|
|
|
{
|
|
|
|
|
|
public double Latitude;
|
|
|
|
|
|
public double Longitude;
|
|
|
|
|
|
public CoordinateEntity(double x, double y) { this.Latitude = x; this.Longitude = y; }
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static async Task<byte[]> DownloadImgAsync(List<MapDataModel.Item> list)
|
|
|
|
|
|
{
|
|
|
|
|
|
var result = new List<CoordinateEntity>();
|
|
|
|
|
|
var count = list.Count;
|
|
|
|
|
|
int segement = (int)Math.Ceiling((double)(count / 1000D));
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i <= count - 1; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (i % segement == 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
result.Add(new CoordinateEntity
|
|
|
|
|
|
{
|
|
|
|
|
|
Latitude = Math.Round(list[i].Point[0], 6),
|
|
|
|
|
|
Longitude = Math.Round(list[i].Point[1], 6),
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return await DownloadImgAsync(result);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static async Task<byte[]> DownloadImgAsync(List<CoordinateEntity> list)
|
|
|
|
|
|
{
|
|
|
|
|
|
var polyline = Encode(list);
|
|
|
|
|
|
var encodeline = UnityWebRequest.EscapeURL(polyline); //HttpUtility.UrlEncode(polyline);
|
|
|
|
|
|
//获取封面图片
|
2021-04-29 18:07:30 +08:00
|
|
|
|
var url = $"https://api.mapbox.com/styles/v1/juzetest/ckmkdjwsa1nvt17nr1ps4fqgs/static/path-4+fff-1({encodeline})/auto/1280x1280?access_token={App.MapBoxAccessToken}";
|
2021-04-22 19:29:59 +08:00
|
|
|
|
HttpClient c = new HttpClient();
|
|
|
|
|
|
var response = await c.GetAsync(url);
|
|
|
|
|
|
if (response.StatusCode == System.Net.HttpStatusCode.OK)
|
|
|
|
|
|
{
|
|
|
|
|
|
byte[] content = await response.Content.ReadAsByteArrayAsync();
|
|
|
|
|
|
return content;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static string GetMapboxApiUrl(List<MapDataModel.Item> list)
|
|
|
|
|
|
{
|
|
|
|
|
|
var result = new List<CoordinateEntity>();
|
|
|
|
|
|
var count = list.Count;
|
|
|
|
|
|
int segement = (int)Math.Ceiling((double)(count / 1000D));
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i <= count - 1; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (i % segement == 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
result.Add(new CoordinateEntity
|
|
|
|
|
|
{
|
|
|
|
|
|
Latitude = Math.Round(list[i].Point[0], 6),
|
|
|
|
|
|
Longitude = Math.Round(list[i].Point[1], 6),
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var polyline = Encode(result);
|
|
|
|
|
|
var encodeline = UnityWebRequest.EscapeURL(polyline); //HttpUtility.UrlEncode(polyline);
|
|
|
|
|
|
//获取封面图片
|
2021-04-29 22:16:32 +08:00
|
|
|
|
var url = $"https://api.mapbox.com/styles/v1/juzetest/ckmkdjwsa1nvt17nr1ps4fqgs/static/path-4+fff-1({encodeline})/auto/1280x768?access_token={App.MapBoxAccessToken}&padding=200&pitch=30";
|
2021-04-22 19:29:59 +08:00
|
|
|
|
return url;
|
|
|
|
|
|
}
|
2021-03-23 16:07:31 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|