mirror of
https://github.com/EDCD/coriolis.git
synced 2025-12-08 22:33:24 +00:00
@@ -1,16 +1,14 @@
|
||||
### STAGE 1: Build ###
|
||||
FROM node:9.11.1-alpine as builder
|
||||
ARG branch=develop
|
||||
ENV BRANCH=$branch
|
||||
ENV BRANCH=master
|
||||
WORKDIR /src/app
|
||||
RUN mkdir -p /src/app/coriolis
|
||||
RUN mkdir -p /src/app/coriolis-data
|
||||
|
||||
RUN apk add --update git
|
||||
|
||||
COPY . /src/app/coriolis
|
||||
|
||||
RUN npm i -g npm
|
||||
ADD https://api.github.com/repos/edcd/coriolis-data/git/refs/heads/master /tmp/version.json
|
||||
|
||||
# Set up coriolis-data
|
||||
WORKDIR /src/app/coriolis-data
|
||||
@@ -19,8 +17,11 @@ RUN git checkout ${BRANCH}
|
||||
RUN npm install --no-package-lock
|
||||
RUN npm start
|
||||
|
||||
|
||||
ADD https://api.github.com/repos/edcd/coriolis/git/refs/heads/master /tmp/version.json
|
||||
# Set up coriolis
|
||||
WORKDIR /src/app/coriolis
|
||||
RUN git clone https://github.com/EDCD/coriolis.git .
|
||||
RUN git checkout ${BRANCH}
|
||||
RUN npm install --no-package-lock
|
||||
RUN npm run build
|
||||
|
||||
36
Dockerfile.dev
Normal file
36
Dockerfile.dev
Normal file
@@ -0,0 +1,36 @@
|
||||
### STAGE 1: Build ###
|
||||
FROM node:9.11.1-alpine as builder
|
||||
ENV BRANCH=develop
|
||||
WORKDIR /src/app
|
||||
RUN mkdir -p /src/app/coriolis
|
||||
RUN mkdir -p /src/app/coriolis-data
|
||||
|
||||
RUN apk add --update git
|
||||
|
||||
RUN npm i -g npm
|
||||
|
||||
ADD https://api.github.com/repos/edcd/coriolis-data/git/refs/heads/develop /tmp/version.json
|
||||
# Set up coriolis-data
|
||||
WORKDIR /src/app/coriolis-data
|
||||
RUN git clone https://github.com/EDCD/coriolis-data.git .
|
||||
RUN git checkout ${BRANCH}
|
||||
RUN npm install --no-package-lock
|
||||
RUN npm start
|
||||
|
||||
|
||||
ADD https://api.github.com/repos/edcd/coriolis/git/refs/heads/develop /tmp/version.json
|
||||
# Set up coriolis
|
||||
WORKDIR /src/app/coriolis
|
||||
RUN git clone https://github.com/EDCD/coriolis.git .
|
||||
RUN git checkout ${BRANCH}
|
||||
RUN npm install --no-package-lock
|
||||
RUN npm run build
|
||||
|
||||
|
||||
### STAGE 2: Production Environment ###
|
||||
FROM fholzer/nginx-brotli as web
|
||||
COPY nginx.conf /etc/nginx/nginx.conf
|
||||
COPY --from=builder /src/app/coriolis/build /usr/share/nginx/html
|
||||
WORKDIR /usr/share/nginx/html
|
||||
EXPOSE 80
|
||||
CMD ["nginx", "-c", "/etc/nginx/nginx.conf", "-g", "daemon off;"]
|
||||
@@ -1,50 +1,50 @@
|
||||
{
|
||||
"type_6_transporter": {
|
||||
"Cargo": "A0p0tdFal8d8s8f4-----04040303430101.Iw1/kA==.Aw1/kA==.",
|
||||
"Miner": "A0p5tdFal8d8s8f42l2l---040403451q0101.Iw1/kA==.Aw1/kA==.",
|
||||
"Hopper": "A0p0tdFal8d0s8f41717---030302024300-.Iw1/kA==.Aw1/kA==."
|
||||
"Cargo": "A0p0tdFal8d8s8f4-----04040303430101-.Iw18UA==.Aw18UA==.",
|
||||
"Miner": "A0p5tdFal8d8s8f42l2l---040403451q0101-.Iw18UA==.Aw18UA==.",
|
||||
"Hopper": "A0p0tdFal8d0s8f41717---030302024300--.Iw18UA==.Aw18UA==."
|
||||
},
|
||||
"type_7_transport": {
|
||||
"Cargo": "A0p0tiFfliddsdf5--------0505040403480101.Iw18aQ==.Aw18aQ==.",
|
||||
"Miner": "A0pdtiFflid8sdf5--2l2l----0505041v03450000.Iw18aQ==.Aw18aQ==."
|
||||
"Cargo": "A0p0tiFfliddsdf5--------0505040403480101--.Iw18eQ==.Aw18eQ==.",
|
||||
"Miner": "A0pdtiFflid8sdf5--2l2l----0505041v03450000--.Iw18eQ==.Aw18eQ==."
|
||||
},
|
||||
"federal_dropship": {
|
||||
"Cargo": "A0pdtiFflnddsif4-1717------05040448--020201.Iw18eQ==.Aw18eQ==."
|
||||
"Cargo": "A0pdtiFflnddsif4-1717------05040448--020201-.Iw18RQ==.Aw18RQ==."
|
||||
},
|
||||
"asp": {
|
||||
"Miner": "A2pftfFflidfskf50s0s24242l2l---04054a1q02022o27.Iw18WQ==.Aw18WQ==."
|
||||
"Miner": "A2pftfFflidfskf50s0s24242l2l---04054a1q02022o27-.Iw18eQ==.Aw18eQ==."
|
||||
},
|
||||
"imperial_clipper": {
|
||||
"Cargo": "A0p5tiFflndisnf4--0s0s----0605450302020101.Iw18aQ==.Aw18aQ==.",
|
||||
"Dream": "A2pktkFflndpskf40v0v0s0s0404040n4k5n5d2b29292o-.AwRj4yWU1I==.CwBhCYy6YRigzLIA.",
|
||||
"Current": "A0patkFflndfskf4----------------.AwRj4yWU1I==.CwBhCYy6YRigzLIA."
|
||||
"Cargo": "A0p5tiFflndisnf4--0s0s----0605450302020101-.Iw18WQ==.Aw18WQ==.",
|
||||
"Dream": "A2pktkFflndpskf40v0v0s0s0404040n4k5n5d2b29292o--.AwRj4yWU1Yg=.CwBhCYy6YRigzPIA.",
|
||||
"Current": "A0patkFflndfskf4-----------------.AwRj4yWU1Yg=.CwBhCYy6YRigzPIA."
|
||||
},
|
||||
"type_9_heavy": {
|
||||
"Current": "A0patsFklndnsif6---------0706054a0303020224.AwRj4yoo.EwBhEYy6dsg=."
|
||||
"Current": "A0patsFklndnsif6---------0706054a0303020224--.AwRj4yo5iA==.EwBhEYy6d6g=."
|
||||
},
|
||||
"python": {
|
||||
"Cargo": "A0patnFflidsssf5---------050505040448020201.Iw18eQ==.Aw18eQ==.",
|
||||
"Miner": "A0pktkFflidpspf50v0v0v2m2m0404--050505Ce4a1v02022o.Iw18eQ==.IwBhBYy6dkCYg===.",
|
||||
"Dream": "A2pptkFfliduspf50v0v0v27270404040m5n5n4f2d2d032t0201.Iw1+gDBxA===.EwBhEYy6e0WEA===.",
|
||||
"Missile": "A0pttoFjljdystf52f2g2d2ePh----04044j03---002h.Iw18eQ==.Aw18eQ==."
|
||||
"Cargo": "A0patnFflidsssf5---------050505040448020201-.Iw18eAMQ.Aw18RQ==.",
|
||||
"Miner": "A0pktkFflidpspf50v0v0v2m2m0404--050505Ce4a1v02022o-.Iw18eAMQ.IwBhBYy6dkCYRA==.",
|
||||
"Dream": "A2pptkFfliduspf50v0v0v27270404040m5n5n4f2d2d032t0201-.Iw1+gDByUA==.EwBhEYy6e0VEA===.",
|
||||
"Missile": "A0pttoFjljdystf52f2g2d2ePh----04044j03---00--.Iw18eAMQ.Aw18RQ==."
|
||||
},
|
||||
"anaconda": {
|
||||
"Dream": "A4putpFklndzsuf52c0o0o0o1m1m0q0q0404040l0b0100004k5n5n112d2d04-0303326b.AwRj4yo5dyg=.MwBhCYy6duvARiA=.",
|
||||
"Cargo": "A0patnFklndnsxf5----------------06050505040404-45030301.Iw18ZVA=.Aw18ZVA=.",
|
||||
"Current": "A0patnFklndksxf5----------------06050505040404-03034524.Iw18ZVA=.Aw18ZVA=.",
|
||||
"Explorer": "A0patnFklndksxf5--------0202------f7050505040s37-2f2i4524.AwRj4yVKJ9hA.AwhMIyumQRhEA===.",
|
||||
"Test": "A4putkFklkdzsuf52c0o0o0o1m1m0q0q0404-0l0b0100034k5n052d04---0303326b.Iw18ZVA=.Aw18ZVA=."
|
||||
"Dream": "A4putpFklndzsuf52c0o0o0o1m1m0q0q0404040l0b0100004k5n5n112d2d04-0303326b-.AwRj4yo5dzhA.MwBhCYy6duvARhEA.",
|
||||
"Cargo": "A0patnFklndnsxf5----------------06050505040404-45030301-.Iw18ZUAxA===.Aw18ZXEA.",
|
||||
"Current": "A0patnFklndksxf5----------------06050505040404-03034524-.Iw18ZUAxA===.Aw18ZXEA.",
|
||||
"Explorer": "A0patnFklndksxf5--------0202------f7050505040s37--2i4524-.AwRj4yVKJ9jCA===.AwhMIyumQRgkA===.",
|
||||
"Test": "A4putkFklkdzsuf52c0o0o0o1m1m0q0q0404-0l0b0100034k5n052d04---0303326b-.Iw18ZUAxA===.Aw18ZXEA."
|
||||
},
|
||||
"diamondback_explorer": {
|
||||
"Explorer": "A0p0tdFfldddsdf5---0202--320p432i2f-.AwRj4zTYg===.AwiMIyoo."
|
||||
"Explorer": "A0p0tdFfldddsdf5---0202--320p432i----.AwRj4zTZaA==.AwiMIyqo."
|
||||
},
|
||||
"vulture": {
|
||||
"Bounty Hunter": "A3patcFalddksff31e1e0404-0l4a-5d27662j.AwRj4z2I.MwBhBYy6oJmAjLIA."
|
||||
"Bounty Hunter": "A3patcFalddksff31e1e0404-0l4a-5d27662j--.AwRj4z2Gg===.MwBhBYy6oJmAjLMQ."
|
||||
},
|
||||
"fer_de_lance": {
|
||||
"Attack": "A2pfthFalidpsff31r0s0s0s0s000404-04-4a-5d27-.Iw18aQ==.CwBhrSu8EZyA."
|
||||
"Attack": "A2pfthFalidpsff31r0s0s0s0s000404-04-4a-5d27--.Iw18aAMQ.CwBhrSu8EZxEA===."
|
||||
},
|
||||
"eagle": {
|
||||
"Figther": "A4p0t5F5l3d5s5f20p0p24-4053-2j-.Iw18kA==.Aw18kA==."
|
||||
"Figther": "A4p0t5F5l3d5s5f20p0p24-4053-2j---.Iw18gDJQ.Aw19kA==."
|
||||
}
|
||||
}
|
||||
|
||||
366
__tests__/fixtures/slef-multiple-builds.json
Normal file
366
__tests__/fixtures/slef-multiple-builds.json
Normal file
@@ -0,0 +1,366 @@
|
||||
[
|
||||
{
|
||||
"header": {
|
||||
"appName": "Inara",
|
||||
"appVersion": "1.0",
|
||||
"appURL": "https:\/\/inara.cz\/cmdr-fleet\/123\/123\/",
|
||||
"appCustomProperties": {
|
||||
"inaraCommanderID": 123,
|
||||
"inaraShipID": 123
|
||||
}
|
||||
},
|
||||
"data": {
|
||||
"Ship": "krait_mkii",
|
||||
"ShipID": 7,
|
||||
"ShipName": "pancake hammer",
|
||||
"ShipIdent": "PH-01",
|
||||
"HullValue": 44160710,
|
||||
"ModulesValue": 111274094,
|
||||
"Rebuy": 7771743,
|
||||
"Modules": [
|
||||
{
|
||||
"Slot": "largehardpoint1",
|
||||
"Item": "hpt_mininglaser_fixed_small",
|
||||
"On": true
|
||||
},
|
||||
{
|
||||
"Slot": "largehardpoint2",
|
||||
"Item": "hpt_cannon_gimbal_large",
|
||||
"On": true,
|
||||
"Engineering": {
|
||||
"BlueprintName": "weapon_overcharged",
|
||||
"Level": 2,
|
||||
"Quality": 1,
|
||||
"ExperimentalEffect": "special_auto_loader"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Slot": "largehardpoint3",
|
||||
"Item": "hpt_cannon_gimbal_large",
|
||||
"On": true,
|
||||
"Engineering": {
|
||||
"BlueprintName": "weapon_overcharged",
|
||||
"Level": 2,
|
||||
"Quality": 1,
|
||||
"ExperimentalEffect": "special_auto_loader"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Slot": "mediumhardpoint1",
|
||||
"Item": "hpt_basicmissilerack_fixed_medium",
|
||||
"On": true,
|
||||
"Engineering": {
|
||||
"BlueprintName": "weapon_highcapacity",
|
||||
"Level": 5,
|
||||
"Quality": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"Slot": "mediumhardpoint2",
|
||||
"Item": "hpt_basicmissilerack_fixed_medium",
|
||||
"On": true
|
||||
},
|
||||
{
|
||||
"Slot": "tinyhardpoint1",
|
||||
"Item": "hpt_heatsinklauncher_turret_tiny",
|
||||
"On": true
|
||||
},
|
||||
{
|
||||
"Slot": "tinyhardpoint2",
|
||||
"Item": "hpt_cloudscanner_size0_class3",
|
||||
"On": true
|
||||
},
|
||||
{
|
||||
"Slot": "tinyhardpoint3",
|
||||
"Item": "hpt_shieldbooster_size0_class5",
|
||||
"On": true
|
||||
},
|
||||
{
|
||||
"Slot": "tinyhardpoint4",
|
||||
"Item": "hpt_shieldbooster_size0_class5",
|
||||
"On": true,
|
||||
"Priority": 1
|
||||
},
|
||||
{
|
||||
"Slot": "slot01_size6",
|
||||
"Item": "int_cargorack_size6_class1",
|
||||
"On": true,
|
||||
"Priority": 1
|
||||
},
|
||||
{
|
||||
"Slot": "slot02_size6",
|
||||
"Item": "int_cargorack_size6_class1",
|
||||
"On": true,
|
||||
"Priority": 1
|
||||
},
|
||||
{
|
||||
"Slot": "slot03_size5",
|
||||
"Item": "int_guardianfsdbooster_size5",
|
||||
"On": true
|
||||
},
|
||||
{
|
||||
"Slot": "slot04_size5",
|
||||
"Item": "int_fighterbay_size5_class1",
|
||||
"On": true
|
||||
},
|
||||
{
|
||||
"Slot": "slot05_size4",
|
||||
"Item": "int_shieldgenerator_size4_class5",
|
||||
"On": true
|
||||
},
|
||||
{
|
||||
"Slot": "slot06_size3",
|
||||
"Item": "int_dronecontrol_collection_size3_class4",
|
||||
"On": true
|
||||
},
|
||||
{
|
||||
"Slot": "slot07_size3",
|
||||
"Item": "int_dronecontrol_collection_size3_class4",
|
||||
"On": true
|
||||
},
|
||||
{
|
||||
"Slot": "slot08_size2",
|
||||
"Item": "int_refinery_size2_class2",
|
||||
"On": true
|
||||
},
|
||||
{
|
||||
"Slot": "slot09_size1",
|
||||
"Item": "int_dronecontrol_prospector_size1_class4",
|
||||
"On": true
|
||||
},
|
||||
{
|
||||
"Slot": "powerplant",
|
||||
"Item": "int_powerplant_size7_class5",
|
||||
"On": true,
|
||||
"Priority": 1
|
||||
},
|
||||
{
|
||||
"Slot": "mainengines",
|
||||
"Item": "int_engine_size6_class5",
|
||||
"On": true
|
||||
},
|
||||
{
|
||||
"Slot": "frameshiftdrive",
|
||||
"Item": "int_hyperdrive_size5_class5",
|
||||
"On": true,
|
||||
"Engineering": {
|
||||
"BlueprintName": "fsd_longrange",
|
||||
"Level": 2,
|
||||
"Quality": 0.861
|
||||
}
|
||||
},
|
||||
{
|
||||
"Slot": "lifesupport",
|
||||
"Item": "int_lifesupport_size4_class2",
|
||||
"On": true,
|
||||
"Priority": 3
|
||||
},
|
||||
{
|
||||
"Slot": "powerdistributor",
|
||||
"Item": "int_powerdistributor_size7_class5",
|
||||
"On": true
|
||||
},
|
||||
{
|
||||
"Slot": "radar",
|
||||
"Item": "int_sensors_size6_class2",
|
||||
"On": true
|
||||
},
|
||||
{
|
||||
"Slot": "fueltank",
|
||||
"Item": "int_fueltank_size5_class3",
|
||||
"On": true,
|
||||
"Priority": 1
|
||||
},
|
||||
{
|
||||
"Slot": "armour",
|
||||
"Item": "krait_mkii_armour_grade3",
|
||||
"On": true,
|
||||
"Priority": 1,
|
||||
"Engineering": {
|
||||
"BlueprintName": "armour_heavyduty",
|
||||
"Level": 5,
|
||||
"Quality": 1
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"header": {
|
||||
"appName": "Inara",
|
||||
"appVersion": "1.0",
|
||||
"appURL": "https:\/\/inara.cz\/cmdr-fleet\/123\/123\/",
|
||||
"appCustomProperties": {
|
||||
"inaraCommanderID": 123,
|
||||
"inaraShipID": 123
|
||||
}
|
||||
},
|
||||
"data": {
|
||||
"Ship": "diamondbackxl",
|
||||
"ShipID": 11,
|
||||
"ShipName": "star Hopper",
|
||||
"ShipIdent": "PH-02",
|
||||
"HullValue": 1615649,
|
||||
"ModulesValue": 16981039,
|
||||
"Rebuy": 929837,
|
||||
"Modules": [
|
||||
{
|
||||
"Slot": "tinyhardpoint1",
|
||||
"Item": "hpt_heatsinklauncher_turret_tiny",
|
||||
"On": true,
|
||||
"Value": 3072
|
||||
},
|
||||
{
|
||||
"Slot": "slot01_size4",
|
||||
"Item": "int_fuelscoop_size4_class5",
|
||||
"On": true,
|
||||
"Priority": 3,
|
||||
"Value": 2862364
|
||||
},
|
||||
{
|
||||
"Slot": "slot02_size4",
|
||||
"Item": "int_guardianfsdbooster_size4",
|
||||
"On": true,
|
||||
"Value": 2847499
|
||||
},
|
||||
{
|
||||
"Slot": "slot03_size3",
|
||||
"Item": "int_shieldgenerator_size3_class2",
|
||||
"On": true,
|
||||
"Value": 18812,
|
||||
"Engineering": {
|
||||
"BlueprintName": "shieldgenerator_thermic",
|
||||
"Level": 3,
|
||||
"Quality": 1,
|
||||
"ExperimentalEffect": "special_shield_health"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Slot": "slot04_size3",
|
||||
"Item": "int_repairer_size3_class5",
|
||||
"On": true,
|
||||
"Value": 2302911
|
||||
},
|
||||
{
|
||||
"Slot": "slot05_size2",
|
||||
"Item": "int_buggybay_size2_class2",
|
||||
"On": true,
|
||||
"Priority": 3,
|
||||
"Value": 21600
|
||||
},
|
||||
{
|
||||
"Slot": "slot06_size2",
|
||||
"Item": "int_cargorack_size2_class1",
|
||||
"On": true,
|
||||
"Priority": 1,
|
||||
"Value": 2852
|
||||
},
|
||||
{
|
||||
"Slot": "slot07_size1",
|
||||
"Item": "int_supercruiseassist",
|
||||
"On": true,
|
||||
"Priority": 3,
|
||||
"Value": 9121
|
||||
},
|
||||
{
|
||||
"Slot": "slot08_size1",
|
||||
"Item": "int_detailedsurfacescanner_tiny",
|
||||
"On": true,
|
||||
"Value": 250000,
|
||||
"Engineering": {
|
||||
"BlueprintName": "sensor_expanded",
|
||||
"Level": 5,
|
||||
"Quality": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"Slot": "powerplant",
|
||||
"Item": "int_powerplant_size4_class5",
|
||||
"On": true,
|
||||
"Priority": 1,
|
||||
"Value": 1441233,
|
||||
"Engineering": {
|
||||
"BlueprintName": "powerplant_boosted",
|
||||
"Level": 1,
|
||||
"Quality": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"Slot": "mainengines",
|
||||
"Item": "int_engine_size4_class5",
|
||||
"On": true,
|
||||
"Value": 1610080,
|
||||
"Engineering": {
|
||||
"BlueprintName": "engine_dirty",
|
||||
"Level": 5,
|
||||
"Quality": 1,
|
||||
"ExperimentalEffect": "special_engine_lightweight"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Slot": "frameshiftdrive",
|
||||
"Item": "int_hyperdrive_size5_class5",
|
||||
"On": true,
|
||||
"Value": 5103953,
|
||||
"Engineering": {
|
||||
"BlueprintName": "fsd_longrange",
|
||||
"Level": 5,
|
||||
"Quality": 1,
|
||||
"ExperimentalEffect": "special_fsd_lightweight"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Slot": "lifesupport",
|
||||
"Item": "int_lifesupport_size3_class2",
|
||||
"On": true,
|
||||
"Value": 10133,
|
||||
"Engineering": {
|
||||
"BlueprintName": "misc_lightweight",
|
||||
"Level": 3,
|
||||
"Quality": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"Slot": "powerdistributor",
|
||||
"Item": "int_powerdistributor_size4_class5",
|
||||
"On": true,
|
||||
"Value": 389022,
|
||||
"Engineering": {
|
||||
"BlueprintName": "powerdistributor_highfrequency",
|
||||
"Level": 4,
|
||||
"Quality": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"Slot": "radar",
|
||||
"Item": "int_sensors_size3_class2",
|
||||
"On": true,
|
||||
"Value": 10133,
|
||||
"Engineering": {
|
||||
"BlueprintName": "sensor_lightweight",
|
||||
"Level": 5,
|
||||
"Quality": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"Slot": "fueltank",
|
||||
"Item": "int_fueltank_size5_class3",
|
||||
"On": true,
|
||||
"Priority": 1,
|
||||
"Value": 97754
|
||||
},
|
||||
{
|
||||
"Slot": "armour",
|
||||
"Item": "diamondbackxl_armour_grade1",
|
||||
"On": true,
|
||||
"Priority": 1,
|
||||
"Engineering": {
|
||||
"BlueprintName": "armour_heavyduty",
|
||||
"Level": 5,
|
||||
"Quality": 1
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
8
__tests__/fixtures/slef-multiple-expected-builds.json
Normal file
8
__tests__/fixtures/slef-multiple-expected-builds.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"krait_mkii": {
|
||||
"Imported pancake hammer": "A2pptkFflidussf52l1o1o2g2g020g040405051Ofr45C9C91oP3.Iw18eQ==.AwRgzKIkA===."
|
||||
},
|
||||
"diamondback_explorer": {
|
||||
"Imported star Hopper": "A0pataFflddfsdf5---02---321P430iv6013w2i.Iw18SQ==.AwRm44GYpKg=."
|
||||
}
|
||||
}
|
||||
188
__tests__/fixtures/slef-single-build.json
Normal file
188
__tests__/fixtures/slef-single-build.json
Normal file
@@ -0,0 +1,188 @@
|
||||
[
|
||||
{
|
||||
"header": {
|
||||
"appName": "Inara",
|
||||
"appVersion": "1.0",
|
||||
"appURL": "https:\/\/inara.cz\/cmdr-fleet\/123\/123\/",
|
||||
"appCustomProperties": {
|
||||
"inaraCommanderID": 123,
|
||||
"inaraShipID": 123
|
||||
}
|
||||
},
|
||||
"data": {
|
||||
"Ship": "krait_mkii",
|
||||
"ShipID": 7,
|
||||
"ShipName": "pancake hammer",
|
||||
"ShipIdent": "PH-01",
|
||||
"HullValue": 44160710,
|
||||
"ModulesValue": 111274094,
|
||||
"Rebuy": 7771743,
|
||||
"Modules": [
|
||||
{
|
||||
"Slot": "largehardpoint1",
|
||||
"Item": "hpt_mininglaser_fixed_small",
|
||||
"On": true
|
||||
},
|
||||
{
|
||||
"Slot": "largehardpoint2",
|
||||
"Item": "hpt_cannon_gimbal_large",
|
||||
"On": true,
|
||||
"Engineering": {
|
||||
"BlueprintName": "weapon_overcharged",
|
||||
"Level": 2,
|
||||
"Quality": 1,
|
||||
"ExperimentalEffect": "special_auto_loader"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Slot": "largehardpoint3",
|
||||
"Item": "hpt_cannon_gimbal_large",
|
||||
"On": true,
|
||||
"Engineering": {
|
||||
"BlueprintName": "weapon_overcharged",
|
||||
"Level": 2,
|
||||
"Quality": 1,
|
||||
"ExperimentalEffect": "special_auto_loader"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Slot": "mediumhardpoint1",
|
||||
"Item": "hpt_basicmissilerack_fixed_medium",
|
||||
"On": true,
|
||||
"Engineering": {
|
||||
"BlueprintName": "weapon_highcapacity",
|
||||
"Level": 5,
|
||||
"Quality": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"Slot": "mediumhardpoint2",
|
||||
"Item": "hpt_basicmissilerack_fixed_medium",
|
||||
"On": true
|
||||
},
|
||||
{
|
||||
"Slot": "tinyhardpoint1",
|
||||
"Item": "hpt_heatsinklauncher_turret_tiny",
|
||||
"On": true
|
||||
},
|
||||
{
|
||||
"Slot": "tinyhardpoint2",
|
||||
"Item": "hpt_cloudscanner_size0_class3",
|
||||
"On": true
|
||||
},
|
||||
{
|
||||
"Slot": "tinyhardpoint3",
|
||||
"Item": "hpt_shieldbooster_size0_class5",
|
||||
"On": true
|
||||
},
|
||||
{
|
||||
"Slot": "tinyhardpoint4",
|
||||
"Item": "hpt_shieldbooster_size0_class5",
|
||||
"On": true,
|
||||
"Priority": 1
|
||||
},
|
||||
{
|
||||
"Slot": "slot01_size6",
|
||||
"Item": "int_cargorack_size6_class1",
|
||||
"On": true,
|
||||
"Priority": 1
|
||||
},
|
||||
{
|
||||
"Slot": "slot02_size6",
|
||||
"Item": "int_cargorack_size6_class1",
|
||||
"On": true,
|
||||
"Priority": 1
|
||||
},
|
||||
{
|
||||
"Slot": "slot03_size5",
|
||||
"Item": "int_guardianfsdbooster_size5",
|
||||
"On": true
|
||||
},
|
||||
{
|
||||
"Slot": "slot04_size5",
|
||||
"Item": "int_fighterbay_size5_class1",
|
||||
"On": true
|
||||
},
|
||||
{
|
||||
"Slot": "slot05_size4",
|
||||
"Item": "int_shieldgenerator_size4_class5",
|
||||
"On": true
|
||||
},
|
||||
{
|
||||
"Slot": "slot06_size3",
|
||||
"Item": "int_dronecontrol_collection_size3_class4",
|
||||
"On": true
|
||||
},
|
||||
{
|
||||
"Slot": "slot07_size3",
|
||||
"Item": "int_dronecontrol_collection_size3_class4",
|
||||
"On": true
|
||||
},
|
||||
{
|
||||
"Slot": "slot08_size2",
|
||||
"Item": "int_refinery_size2_class2",
|
||||
"On": true
|
||||
},
|
||||
{
|
||||
"Slot": "slot09_size1",
|
||||
"Item": "int_dronecontrol_prospector_size1_class4",
|
||||
"On": true
|
||||
},
|
||||
{
|
||||
"Slot": "powerplant",
|
||||
"Item": "int_powerplant_size7_class5",
|
||||
"On": true,
|
||||
"Priority": 1
|
||||
},
|
||||
{
|
||||
"Slot": "mainengines",
|
||||
"Item": "int_engine_size6_class5",
|
||||
"On": true
|
||||
},
|
||||
{
|
||||
"Slot": "frameshiftdrive",
|
||||
"Item": "int_hyperdrive_size5_class5",
|
||||
"On": true,
|
||||
"Engineering": {
|
||||
"BlueprintName": "fsd_longrange",
|
||||
"Level": 2,
|
||||
"Quality": 0.861
|
||||
}
|
||||
},
|
||||
{
|
||||
"Slot": "lifesupport",
|
||||
"Item": "int_lifesupport_size4_class2",
|
||||
"On": true,
|
||||
"Priority": 3
|
||||
},
|
||||
{
|
||||
"Slot": "powerdistributor",
|
||||
"Item": "int_powerdistributor_size7_class5",
|
||||
"On": true
|
||||
},
|
||||
{
|
||||
"Slot": "radar",
|
||||
"Item": "int_sensors_size6_class2",
|
||||
"On": true
|
||||
},
|
||||
{
|
||||
"Slot": "fueltank",
|
||||
"Item": "int_fueltank_size5_class3",
|
||||
"On": true,
|
||||
"Priority": 1
|
||||
},
|
||||
{
|
||||
"Slot": "armour",
|
||||
"Item": "krait_mkii_armour_grade3",
|
||||
"On": true,
|
||||
"Priority": 1,
|
||||
"Engineering": {
|
||||
"BlueprintName": "armour_heavyduty",
|
||||
"Level": 5,
|
||||
"Quality": 1
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -18,13 +18,13 @@ describe('Import Modal', function() {
|
||||
const mockContext = {
|
||||
language: getLanguage('en'),
|
||||
sizeRatio: 1,
|
||||
openMenu: jest.genMockFunction(),
|
||||
closeMenu: jest.genMockFunction(),
|
||||
showModal: jest.genMockFunction(),
|
||||
hideModal: jest.genMockFunction(),
|
||||
tooltip: jest.genMockFunction(),
|
||||
termtip: jest.genMockFunction(),
|
||||
onWindowResize: jest.genMockFunction()
|
||||
openMenu: jest.fn(),
|
||||
closeMenu: jest.fn(),
|
||||
showModal: jest.fn(),
|
||||
hideModal: jest.fn(),
|
||||
tooltip: jest.fn(),
|
||||
termtip: jest.fn(),
|
||||
onWindowResize: jest.fn()
|
||||
};
|
||||
|
||||
let modal, render, ContextProvider = Utils.createContextProvider(mockContext);
|
||||
@@ -110,21 +110,25 @@ describe('Import Modal', function() {
|
||||
it('catches an invalid backup', function() {
|
||||
const importData = require('./fixtures/valid-backup');
|
||||
let invalidImportData = Object.assign({}, importData);
|
||||
//invalidImportData.builds.asp = null; // Remove Asp Miner build used in comparison
|
||||
// Remove Asp Miner build used in comparison
|
||||
delete(invalidImportData.builds.asp);
|
||||
|
||||
pasteText('"this is not valid"');
|
||||
expect(modal.state.importValid).toBeFalsy();
|
||||
expect(modal.state.errorMsg).toEqual('Must be an object or array!');
|
||||
|
||||
pasteText('{ "builds": "Should not be a string" }');
|
||||
expect(modal.state.importValid).toBeFalsy();
|
||||
expect(modal.state.errorMsg).toEqual('builds must be an object!');
|
||||
pasteText(JSON.stringify(importData).replace('anaconda', 'invalid_ship'));
|
||||
|
||||
pasteText(JSON.stringify(importData).replace(/anaconda/g, 'invalid_ship'));
|
||||
expect(modal.state.importValid).toBeFalsy();
|
||||
expect(modal.state.errorMsg).toEqual('"invalid_ship" is not a valid Ship Id!');
|
||||
expect(Object.keys(modal.state.builds)).not.toContain('anaconda');
|
||||
|
||||
pasteText(JSON.stringify(importData).replace('Dream', ''));
|
||||
expect(modal.state.importValid).toBeFalsy();
|
||||
expect(modal.state.errorMsg).toEqual('Imperial Clipper build "" must be a string at least 1 character long!');
|
||||
expect(Object.keys(modal.state.builds.imperial_clipper).length).toEqual(3);
|
||||
|
||||
pasteText(JSON.stringify(invalidImportData));
|
||||
expect(modal.state.importValid).toBeFalsy();
|
||||
expect(modal.state.errorMsg).toEqual('asp build "Miner" data is missing!');
|
||||
@@ -144,7 +148,7 @@ describe('Import Modal', function() {
|
||||
expect(modal.state.singleBuild).toBe(true);
|
||||
clickProceed();
|
||||
expect(MockRouter.go.mock.calls.length).toBe(1);
|
||||
expect(MockRouter.go.mock.calls[0][0]).toBe('/outfit/anaconda?code=A4putkFklkdzsuf52c0o0o0o1m1m0q0q0404-0l0b0100034k5n052d04---0303326b.AwRj4zNLaA%3D%3D.CwBhCYzBGW9qCTSqq5xA.&bn=Test%20My%20Ship');
|
||||
expect(MockRouter.go.mock.calls[0][0]).toBe('/outfit/anaconda?code=A4putkFklkdzsuf52c0o0o0o1m1m0q0q0404-0l0b0100034k5n052d04---0303326b-.AwRj4zNLeI%3D%3D.CwBhCYzBGW9qCTSqq5JA.&bn=Test%20My%20Ship');
|
||||
});
|
||||
|
||||
it('catches an invalid build', function() {
|
||||
@@ -169,7 +173,7 @@ describe('Import Modal', function() {
|
||||
expect(modal.state.singleBuild).toBe(true);
|
||||
clickProceed();
|
||||
expect(MockRouter.go.mock.calls.length).toBe(1);
|
||||
expect(MockRouter.go.mock.calls[0][0]).toBe('/outfit/anaconda?code=A4putkFklkdzsuf52c0o0o0o1m1m0q0q0404-0l0b0100034k5n052d04---0303326b.AwRj4zNLaA%3D%3D.CwBhCYzBGW9qCTSqq5xA.H4sIAAAAAAAAA2MUe8HMwPD%2FPwMAAGvB0AkAAAA%3D&bn=Test%20My%20Ship');
|
||||
expect(MockRouter.go.mock.calls[0][0]).toBe('/outfit/anaconda?code=A4putkFklkdzsuf52c0o0o0o1m1m0q0q0404-0l0b0100034k5n052d04---0303326b-.AwRj4zNLeI%3D%3D.CwBhCYzBGW9qCTSqq5JA.H4sIAAAAAAAAE2MUe8HMwPD%2FPwMAAGvB0AkAAAA%3D&bn=Test%20My%20Ship');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -186,7 +190,7 @@ describe('Import Modal', function() {
|
||||
expect(modal.state.singleBuild).toBe(true);
|
||||
clickProceed();
|
||||
expect(MockRouter.go.mock.calls.length).toBe(1);
|
||||
expect(MockRouter.go.mock.calls[0][0]).toBe('/outfit/asp?code=A0pftiFflfddsnf5------020202033c044002v62f2i.AwRj4yvI.CwRgDBldHnJA.H4sIAAAAAAAAA2P858DAwPCXEUhwHPvx%2F78YG5AltB7I%2F8%2F0TwImJboDSPJ%2F%2B%2Ff%2Fv%2FKlX%2F%2F%2Fi3AwMTBIfARK%2FGf%2BJwVSxArStVAYqOjvz%2F%2F%2FJVo5GRhE2IBc4SKQSSz%2FDGEmCa398P8%2F%2F2%2BgTf%2F%2FA7kMAExxqlSAAAAA&bn=Multi-purpose%20Asp%20Explorer');
|
||||
expect(MockRouter.go.mock.calls[0][0]).toBe('/outfit/asp?code=A0pftiFflfddsnf5------020202033c044002v6-2i-.AwRj4yvYg%3D%3D%3D.CwRgDBldHn5A.H4sIAAAAAAAAE2P858DAwPCXEUhwHPvx%2F78YG5AltB7I%2F8%2F0TwImJboDSPJ%2F%2B%2Ff%2Fv%2FKlX%2F%2F%2Fi3AwMTBIfARK%2FGf%2BJwVSxArStVAYqOjvz%2F%2F%2FJVo5GRhE2IBc4SKQSSz%2FDGEmCa398P8%2F%2F2%2BgTf%2F%2FA7kMAExxqlSAAAAA&bn=Multi-purpose%20Asp%20Explorer');
|
||||
});
|
||||
|
||||
it('imports a valid v4 build with modifications', function() {
|
||||
@@ -198,11 +202,11 @@ describe('Import Modal', function() {
|
||||
expect(modal.state.singleBuild).toBe(true);
|
||||
clickProceed();
|
||||
expect(MockRouter.go.mock.calls.length).toBe(1);
|
||||
expect(MockRouter.go.mock.calls[0][0]).toBe('/outfit/imperial_courier?code=A0patzF5l0das8f31a1a270202000e402t0101-2f.AwRj4zKA.CwRgDBldLiQ%3D.H4sIAAAAAAAAA12OPUvDYBSFT1OTfkRJjUkbbC3Yj8mlODgUISAtdOlety5ODv0Vgji7O7kJ%2FgzBQX%2BEY7Gg0NKhfY%2FnHQLFDBdynufe9%2BRMCmCb06g29oCgacjiRx6gY6oWKUT8UgLaszqQfHmSnpVFN1uSeXNsJVcj%2FA2EHlZkspIUpUc6UjTXGT85qwHuSEuVc%2F16r99kDQeSSjvSbSjpyUpNK10uJJ3aYqk6smwm1lQ9bOxw71TMm8VanEqq9JW1r3Qo%2BREOLnQHvbWmb7rZIu5VLIyGQGOukPv%2F0WQk5LeEAjPOUDwtAP6bShy2HKAz0HPO%2B5KsP25I79O2I7LvD%2Bz4Il1XAQAA&bn=Multi-purpose%20Imperial%20Courier');
|
||||
expect(MockRouter.go.mock.calls[0][0]).toBe('/outfit/imperial_courier?code=A0patzF5l0das8f31a1a270202000e402t0101----.AwRj4zOYg%3D%3D%3D.CwRgDBldLuZA.H4sIAAAAAAAAE12OPUvDYBSFT1OTfkRJjUkbbC3Yj8mlODgUISAtdOlety5ODv0Vgji7O7kJ%2FgzBQX%2BEY7Gg0NKhfY%2FnHQLFDBdynufe9%2BRMCmCb06g29oCgacjiRx6gY6oWKUT8UgLaszqQfHmSnpVFN1uSeXNsJVcj%2FA2EHlZkspIUpUc6UjTXGT85qwHuSEuVc%2F16r99kDQeSSjvSbSjpyUpNK10uJJ3aYqk6smwm1lQ9bOxw71TMm8VanEqq9JW1r3Qo%2BREOLnQHvbWmb7rZIu5VLIyGQGOukPv%2F0WQk5LeEAjPOUDwtAP6bShy2HKAz0HPO%2B5KsP25I79O2I7LvD%2Bz4Il1XAQAA&bn=Multi-purpose%20Imperial%20Courier');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Import Detaild Builds Array', function() {
|
||||
describe('Import Detailed Builds Array', function() {
|
||||
|
||||
beforeEach(reset);
|
||||
|
||||
@@ -240,7 +244,7 @@ describe('Import Modal', function() {
|
||||
expect(modal.state.singleBuild).toBe(true);
|
||||
clickProceed();
|
||||
expect(MockRouter.go.mock.calls.length).toBe(1);
|
||||
expect(MockRouter.go.mock.calls[0][0]).toBe('/outfit/federal_corvette?code=A2putsFklndzsxf50x0x7l28281919040404040402020l06p05sf63c5ifr--v66g2f.AwRj4zNaqA%3D%3D.CwRgDBldUExuBiIlUA%3D%3D.H4sIAAAAAAAAA12STy8DURTFb1szU53Ga8dg2qqqDmJDIoKFxJImumYjVrVqfAALC4lNbcUnkLCoDbEQu0bSlQVhI8JHsJBIQ73rXMkwMYuT9%2Bb87nl%2F7ovoRSL6ikD6TYNINZg5XsWUo7pfrBikr2USlRyXyDuLAhr6ZHanNLOzD5tjOiskysk5dOBvfTB7bjeRW0MNG3ohSBq1bKKxKwyLLUAjmwjpPu4wJx4xVbNI57heDfbUKUAy2xaRUQZpllHoHMHxKqjhhF4LgjtJiFHDmqbrEeVnUJOax7%2FSdRfRwBNotv9wo5kAuZMD2egKyDYcdYl1OBki6z%2BZQjaFnBPyFCM1LefF%2BcgrY0es9FKwbW8ZYj9gmBbxRVRdglMh6BNqnwsk4ouoO4HSIehNoBuBRHwR1QOmsBvHmk6IfMbd2fdCEka%2BjNSexPWGoEkcyX6CnxbxRZQtd%2BPpym%2B31xFtn0iSFPkf%2BBkttZlzB9KDFyBuFRfAGV0Ogoff8SSsCfjjD5hGWtLIwZB%2FgX5Zt%2BLHMI9My7sp6nzgZzekswTxVvCOkq%2FSXqb%2F3zfLxh6HrwIAAA%3D%3D&bn=Imported%20Federal%20Corvette');
|
||||
expect(MockRouter.go.mock.calls[0][0]).toBe('/outfit/federal_corvette?code=A2putsFklndzsxf50x0x7l28281919040404040402020l06p05sf63c5ifr--v66g--.AwRj4zNapI%3D%3D.CwRgDBldUExuBiIlWIA%3D.&bn=Imported%20Federal%20Corvette');
|
||||
});
|
||||
|
||||
it('imports a valid companion API build', function() {
|
||||
@@ -252,7 +256,7 @@ describe('Import Modal', function() {
|
||||
expect(modal.state.singleBuild).toBe(true);
|
||||
clickProceed();
|
||||
expect(MockRouter.go.mock.calls.length).toBe(1);
|
||||
expect(MockRouter.go.mock.calls[0][0]).toBe('/outfit/beluga?code=A0pktsFplCdpsnf70t0t2727270004040404043c4fmimlmm04mc0iv62i2f.AwRj4yukg%3D%3D%3D.CwRgDBldHi8IUA%3D%3D.H4sIAAAAAAAAA2P8Z8%2FAwPCXEUiIKTMxMPCv%2F%2Ff%2FP8cFIPGf6Z8YTEr0GjMDg%2FJWICERBOTzn%2Fn7%2F7%2FIO5Ai5n9SIEWsQEIoSxAolfbt%2F3%2BJPk4GBhE7YQYGYVmgcuVnf4Aq%2FwOVAAAyiFctbgAAAA%3D%3D&bn=Imported%20Beluga%20Liner');
|
||||
expect(MockRouter.go.mock.calls[0][0]).toBe('/outfit/beluga?code=A0pktsFplCdpsnf70t0t2727270004040404043c4fmimlmm04mc0iv62i--.AwRj4yusg%3D%3D%3D.CwRgDBldHi8IWIA%3D.&bn=Imported%20Beluga%20Liner');
|
||||
});
|
||||
|
||||
it('imports a valid companion API build', function() {
|
||||
@@ -264,7 +268,7 @@ describe('Import Modal', function() {
|
||||
expect(modal.state.singleBuild).toBe(true);
|
||||
clickProceed();
|
||||
expect(MockRouter.go.mock.calls.length).toBe(1);
|
||||
expect(MockRouter.go.mock.calls[0][0]).toBe('/outfit/type_7_transport?code=A0patfFflidasdf5----0404040005050504044d2402.AwRj4yrI.CwRgDBlVK7EiA%3D%3D%3D.&bn=Imported%20Type-7%20Transporter');
|
||||
expect(MockRouter.go.mock.calls[0][0]).toBe('/outfit/type_7_transport?code=A0patfFflidasdf5----0404040005050504044d2402--.AwRj4yoo.CwRgDBlVK7HjEA%3D%3D.&bn=Imported%20Type-7%20Transporter');
|
||||
});
|
||||
|
||||
it('imports a valid companion API build', function() {
|
||||
@@ -276,7 +280,7 @@ describe('Import Modal', function() {
|
||||
expect(modal.state.singleBuild).toBe(true);
|
||||
clickProceed();
|
||||
expect(MockRouter.go.mock.calls.length).toBe(1);
|
||||
expect(MockRouter.go.mock.calls[0][0]).toBe('/outfit/cobra_mk_iii?code=A0p0tdFaldd3sdf4------34---2f2i.AwRj4yKA.CwRgDMYExrezBUg%3D.&bn=Imported%20Cobra%20Mk%20III');
|
||||
expect(MockRouter.go.mock.calls[0][0]).toBe('/outfit/cobra_mk_iii?code=A0p0tdFaldd3sdf4------34----2i--.AwRj4yqA.CwRgDMYExrezBig%3D.&bn=Imported%20Cobra%20Mk%20III');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -324,4 +328,41 @@ describe('Import Modal', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe('Imports SLEF data', () => {
|
||||
beforeEach(reset);
|
||||
|
||||
it('imports a single valid SLEF build', () => {
|
||||
const importData = require('./fixtures/slef-single-build.json');
|
||||
pasteText(JSON.stringify(importData));
|
||||
|
||||
expect(modal.state.importValid).toBeTruthy();
|
||||
expect(modal.state.errorMsg).toEqual(null);
|
||||
expect(modal.state.singleBuild).toBe(true);
|
||||
clickProceed();
|
||||
expect(MockRouter.go.mock.calls.length).toBe(1);
|
||||
expect(MockRouter.go.mock.calls[0][0]).toBe('/outfit/krait_mkii?code=A2pptkFflidussf52l1o1o2g2g020g040405051Ofr45C9C91oP3.Iw18eQ%3D%3D.AwRgzKIkA%3D%3D%3D.&bn=Imported%20pancake%20hammer');
|
||||
});
|
||||
|
||||
it('imports multiple SLEF builds', () => {
|
||||
const importData = require('./fixtures/slef-multiple-builds.json');
|
||||
const expectedBuilds = require('./fixtures/slef-multiple-expected-builds.json');
|
||||
pasteText(JSON.stringify(importData));
|
||||
|
||||
expect(modal.state.importValid).toBeTruthy();
|
||||
expect(modal.state.errorMsg).toEqual(null);
|
||||
expect(modal.state.singleBuild).toBe(false);
|
||||
clickProceed();
|
||||
expect(modal.state.processed).toBeTruthy();
|
||||
clickImport();
|
||||
|
||||
const builds = Persist.getBuilds();
|
||||
|
||||
for (const shipModel in builds) {
|
||||
for (const buildName in builds[shipModel]) {
|
||||
expect(builds[shipModel][buildName])
|
||||
.toEqual(expectedBuilds[shipModel][buildName]);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,55 +1,43 @@
|
||||
version: '2.2'
|
||||
version: '3.6'
|
||||
|
||||
services:
|
||||
coriolis_prod:
|
||||
master:
|
||||
image: edcd/coriolis:master
|
||||
build:
|
||||
dockerfile: Dockerfile
|
||||
context: .
|
||||
args:
|
||||
branch: master
|
||||
restart: always
|
||||
volumes:
|
||||
- ./nginx.conf:/etc/nginx/nginx.conf
|
||||
- ./nginx.conf:/etc/nginx/nginx.conf
|
||||
networks:
|
||||
- web
|
||||
- web
|
||||
labels:
|
||||
- "traefik.docker.network=web"
|
||||
- "traefik.enable=true"
|
||||
- "traefik.basic.frontend.rule=Host:coriolis.io,coriolis.edcd.io"
|
||||
- "traefik.basic.port=80"
|
||||
- "traefik.basic.protocol=http"
|
||||
- "traefik.docker.network=web"
|
||||
- "traefik.enable=true"
|
||||
- "traefik.basic.frontend.rule=Host:coriolis.io,coriolis.edcd.io"
|
||||
- "traefik.basic.port=80"
|
||||
- "traefik.basic.protocol=http"
|
||||
|
||||
coriolis_dev:
|
||||
develop:
|
||||
image: edcd/coriolis:develop
|
||||
build:
|
||||
dockerfile: Dockerfile
|
||||
dockerfile: Dockerfile.dev
|
||||
context: .
|
||||
args:
|
||||
branch: develop
|
||||
restart: always
|
||||
volumes:
|
||||
- ./nginx.conf:/etc/nginx/nginx.conf
|
||||
networks:
|
||||
- web
|
||||
- web
|
||||
labels:
|
||||
- "traefik.docker.network=web"
|
||||
- "traefik.enable=true"
|
||||
- "traefik.basic.frontend.rule=Host:beta.coriolis.io,beta.coriolis.edcd.io"
|
||||
- "traefik.basic.port=80"
|
||||
- "traefik.basic.protocol=http"
|
||||
|
||||
coriolis_dw2:
|
||||
image: edcd/coriolis:dw2
|
||||
restart: always
|
||||
volumes:
|
||||
- ./nginx.conf:/etc/nginx/nginx.conf
|
||||
networks:
|
||||
- web
|
||||
labels:
|
||||
- "traefik.docker.network=web"
|
||||
- "traefik.enable=true"
|
||||
- "traefik.basic.frontend.rule=Host:dw2.coriolis.io"
|
||||
- "traefik.basic.port=80"
|
||||
- "traefik.basic.protocol=http"
|
||||
- "traefik.docker.network=web"
|
||||
- "traefik.enable=true"
|
||||
- "traefik.basic.frontend.rule=Host:beta.coriolis.io,beta.coriolis.edcd.io"
|
||||
- "traefik.basic.port=80"
|
||||
- "traefik.basic.protocol=http"
|
||||
|
||||
networks:
|
||||
web:
|
||||
|
||||
@@ -22,6 +22,7 @@ import ComparisonPage from './pages/ComparisonPage';
|
||||
import ShipyardPage from './pages/ShipyardPage';
|
||||
import ErrorDetails from './pages/ErrorDetails';
|
||||
|
||||
|
||||
const zlib = require('pako');
|
||||
const request = require('superagent');
|
||||
|
||||
@@ -72,7 +73,7 @@ export default class Coriolis extends React.Component {
|
||||
route: {},
|
||||
sizeRatio: Persist.getSizeRatio()
|
||||
};
|
||||
this._getAnnouncements();
|
||||
// this._getAnnouncements();
|
||||
Router('', (r) => this._setPage(ShipyardPage, r));
|
||||
Router('/import?', (r) => this._importBuild(r));
|
||||
Router('/import/:data', (r) => this._importBuild(r));
|
||||
@@ -97,15 +98,30 @@ export default class Coriolis extends React.Component {
|
||||
const json = JSON.parse(data);
|
||||
console.info('Ship import data: ');
|
||||
console.info(json);
|
||||
let ship;
|
||||
if (json && json.modules) {
|
||||
ship = CompanionApiUtils.shipFromJson(json);
|
||||
} else if (json && json.Modules) {
|
||||
ship = JournalUtils.shipFromLoadoutJSON(json);
|
||||
let ship, importString;
|
||||
if (json) {
|
||||
if (json.length && json[0].data) { // SLEF
|
||||
if (json.length > 1) { // Multiple builds, open modal
|
||||
importString = data;
|
||||
} else { // Single build, import directly
|
||||
ship = JournalUtils.shipFromLoadoutJSON(json[0].data);
|
||||
}
|
||||
} else { // not SLEF
|
||||
if (json.modules) {
|
||||
ship = CompanionApiUtils.shipFromJson(json);
|
||||
} else if (json.Modules) {
|
||||
ship = JournalUtils.shipFromLoadoutJSON(json);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ship) {
|
||||
r.params.ship = ship.id;
|
||||
r.params.code = ship.toString();
|
||||
this._setPage(OutfittingPage, r);
|
||||
} else if (importString) {
|
||||
this._setPage(ShipyardPage, r);
|
||||
this._showModal(<ModalImport importString={data}/>);
|
||||
}
|
||||
r.params.ship = ship.id;
|
||||
r.params.code = ship.toString();
|
||||
this._setPage(OutfittingPage, r)
|
||||
} catch (err) {
|
||||
this._onError('Failed to import ship', r.path, 0, 0, err);
|
||||
}
|
||||
@@ -113,8 +129,8 @@ export default class Coriolis extends React.Component {
|
||||
|
||||
async _getAnnouncements() {
|
||||
try {
|
||||
const announces = await request.get('https://orbis.zone/api/announcement')
|
||||
.query({ showInCoriolis: true });
|
||||
const announces = await request.get('https://api.orbis.zone/announcements')
|
||||
.query({ coriolis: true });
|
||||
this.setState({ announcements: announces.body });
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
@@ -394,18 +410,18 @@ export default class Coriolis extends React.Component {
|
||||
*/
|
||||
render() {
|
||||
let currentMenu = this.state.currentMenu;
|
||||
|
||||
return <div style={{ minHeight: '100%' }} onClick={this._closeMenu}
|
||||
className={this.state.noTouch ? 'no-touch' : null}>
|
||||
<Header announcements={this.state.announcements} appCacheUpdate={this.state.appCacheUpdate}
|
||||
currentMenu={currentMenu}/>
|
||||
<div className="announcement-container">{this.state.announcements.map(a => <Announcement
|
||||
text={a.message}/>)}</div>
|
||||
text={a.text}/>)}</div>
|
||||
{this.state.error ? this.state.error : this.state.page ? React.createElement(this.state.page, { currentMenu }) :
|
||||
<NotFoundPage/>}
|
||||
{this.state.modal}
|
||||
{this.state.tooltip}
|
||||
<footer>
|
||||
|
||||
<div className="right cap">
|
||||
<a href="https://github.com/EDCD/coriolis" target="_blank" rel="noopener noreferrer"
|
||||
title="Coriolis Github Project">{window.CORIOLIS_VERSION} - {window.CORIOLIS_DATE}</a>
|
||||
|
||||
@@ -72,6 +72,7 @@ Router.go = function(path, state) {
|
||||
gaTrack(path);
|
||||
let ctx = new Context(path, state);
|
||||
Router.dispatch(ctx);
|
||||
|
||||
if (!ctx.unhandled) {
|
||||
if (isStandAlone()) {
|
||||
Persist.setState(ctx);
|
||||
|
||||
@@ -426,7 +426,10 @@ export default class Header extends TranslatedComponent {
|
||||
if (this.props.announcements) {
|
||||
announcements = [];
|
||||
for (let announce of this.props.announcements) {
|
||||
announcements.push(<Announcement text={announce.message} />);
|
||||
if (announce.expiry < Date.now()) {
|
||||
continue;
|
||||
}
|
||||
announcements.push(<Announcement text={announce.text} />);
|
||||
announcements.push(<hr/>);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,8 @@ import * as ModuleUtils from '../shipyard/ModuleUtils';
|
||||
import { fromDetailedBuild } from '../shipyard/Serializer';
|
||||
import { Download } from './SvgIcons';
|
||||
import { outfitURL } from '../utils/UrlGenerators';
|
||||
import * as CompanionApiUtils from '../utils/CompanionApiUtils';
|
||||
import { shipFromJson, shipModelFromJson } from '../utils/CompanionApiUtils';
|
||||
import { shipFromLoadoutJSON } from '../utils/JournalUtils';
|
||||
|
||||
const zlib = require('pako');
|
||||
|
||||
@@ -88,6 +89,7 @@ export default class ModalImport extends TranslatedComponent {
|
||||
|
||||
|
||||
static propTypes = {
|
||||
importString: PropTypes.string, // Optional: Default data for import modal
|
||||
builds: PropTypes.object, // Optional: Import object
|
||||
};
|
||||
|
||||
@@ -106,7 +108,7 @@ export default class ModalImport extends TranslatedComponent {
|
||||
shipDiscount: null,
|
||||
moduleDiscount: null,
|
||||
errorMsg: null,
|
||||
importString: null,
|
||||
importString: props.importString || null,
|
||||
importValid: false,
|
||||
insurance: null
|
||||
};
|
||||
@@ -214,8 +216,8 @@ export default class ModalImport extends TranslatedComponent {
|
||||
* @throws {string} if parse/import fails
|
||||
*/
|
||||
_importCompanionApiBuild(build) {
|
||||
const shipModel = CompanionApiUtils.shipModelFromJson(build);
|
||||
const ship = CompanionApiUtils.shipFromJson(build);
|
||||
const shipModel = shipModelFromJson(build);
|
||||
const ship = shipFromJson(build);
|
||||
|
||||
let builds = {};
|
||||
builds[shipModel] = {};
|
||||
@@ -321,6 +323,30 @@ export default class ModalImport extends TranslatedComponent {
|
||||
this.setState({ builds, singleBuild: true });
|
||||
}
|
||||
|
||||
/**
|
||||
* Import SLEF formatted builds. Sets state to a map of the builds on success
|
||||
* and flags if there was only a single build.
|
||||
*
|
||||
* @param {string} importData - Array of the list of builds.
|
||||
* @throws {string} If parse / import fails
|
||||
*/
|
||||
_importSlefBuilds(importData) {
|
||||
const builds = importData.reduce((memo, { data }) => {
|
||||
const shipModel = shipModelFromJson(data);
|
||||
const ship = shipFromLoadoutJSON(data);
|
||||
const shipTemplate = Ships[shipModel];
|
||||
const shipName = data.ShipName || shipTemplate.properties.name;
|
||||
|
||||
const key = `Imported ${shipName}`;
|
||||
memo[shipModel] = {};
|
||||
memo[shipModel][key] = ship.toString();
|
||||
|
||||
return memo;
|
||||
}, {});
|
||||
|
||||
this.setState({ builds, singleBuild: Object.keys(builds).length === 1 });
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the import string / text box contents
|
||||
* @param {SyntheticEvent} event Event
|
||||
@@ -355,8 +381,10 @@ export default class ModalImport extends TranslatedComponent {
|
||||
throw 'Must be an object or array!';
|
||||
}
|
||||
|
||||
if (importData.modules != null && importData.modules.Armour != null) { // Only the companion API has this information
|
||||
this._importCompanionApiBuild(importData); // Single sihp definition
|
||||
if (importData?.[0]?.header?.appName) { // has SLEF envelope?
|
||||
this._importSlefBuilds(importData);
|
||||
} else if (importData.modules != null && importData.modules.Armour != null) { // Only the companion API has this information
|
||||
this._importCompanionApiBuild(importData); // Single ship definition
|
||||
} else if (importData.ship != null && importData.ship.modules != null && importData.ship.modules.Armour != null) { // Only the companion API has this information
|
||||
this._importCompanionApiBuild(importData.ship); // Complete API dump
|
||||
} else if (importData instanceof Array) { // Must be detailed export json
|
||||
@@ -542,7 +570,7 @@ export default class ModalImport extends TranslatedComponent {
|
||||
{comparisonRows}
|
||||
</tbody>
|
||||
</table>
|
||||
);
|
||||
);
|
||||
}
|
||||
|
||||
if(this.state.canEdit) {
|
||||
|
||||
@@ -243,8 +243,13 @@ export default class Offence extends TranslatedComponent {
|
||||
<td className='ri'><span onMouseOver={termtip.bind(null, baseSDpsTooltipDetails)} onMouseOut={tooltip.bind(null, null)}>{formats.f1(weapon.sdps.base.total)}</span></td>
|
||||
<td className='ri'><span onMouseOver={termtip.bind(null, effectiveShieldsSDpsTooltipDetails)} onMouseOut={tooltip.bind(null, null)}>{formats.f1(weapon.sdps.shields.total)}</span></td>
|
||||
<td className='ri'><span onMouseOver={termtip.bind(null, effectivenessShieldsTooltipDetails)} onMouseOut={tooltip.bind(null, null)}>{formats.pct1(weapon.effectiveness.shields.total)}</span></td>
|
||||
|
||||
<td className='ri'><span>{formats.f1(weapon.effectiveness.shields.dpe)}</span></td>
|
||||
|
||||
<td className='ri'><span onMouseOver={termtip.bind(null, effectiveArmourSDpsTooltipDetails)} onMouseOut={tooltip.bind(null, null)}>{formats.f1(weapon.sdps.armour.total)}</span></td>
|
||||
<td className='ri'><span onMouseOver={termtip.bind(null, effectivenessArmourTooltipDetails)} onMouseOut={tooltip.bind(null, null)}>{formats.pct1(weapon.effectiveness.armour.total)}</span></td>
|
||||
|
||||
<td className='ri'><span>{formats.f1(weapon.effectiveness.armour.dpe)}</span></td>
|
||||
</tr>);
|
||||
}
|
||||
|
||||
@@ -271,15 +276,20 @@ export default class Offence extends TranslatedComponent {
|
||||
<tr className='main'>
|
||||
<th rowSpan='2' className='sortable' onClick={sortOrder.bind(this, 'n')}>{translate('weapon')}</th>
|
||||
<th colSpan='1'>{translate('overall')}</th>
|
||||
<th colSpan='2'>{translate('opponent\'s shields')}</th>
|
||||
<th colSpan='2'>{translate('opponent\'s armour')}</th>
|
||||
<th colSpan='3'>{translate('opponent\'s shields')}</th>
|
||||
<th colSpan='3'>{translate('opponent\'s armour')}</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th className='lft sortable' onMouseOver={termtip.bind(null, 'TT_EFFECTIVE_SDPS_SHIELDS')} onMouseOut={tooltip.bind(null, null)} onClick={sortOrder.bind(this, 'esdpss')}>{'sdps'}</th>
|
||||
<th className='lft sortable' onMouseOver={termtip.bind(null, 'TT_EFFECTIVE_SDPS_SHIELDS')} onMouseOut={tooltip.bind(null, null)} onClick={sortOrder.bind(this, 'esdpss')}>{'sdps'}</th>
|
||||
<th className='sortable' onMouseOver={termtip.bind(null, 'TT_EFFECTIVENESS_SHIELDS')} onMouseOut={tooltip.bind(null, null)}onClick={sortOrder.bind(this, 'es')}>{'eft'}</th>
|
||||
|
||||
<th className='sortable'>{'dpe'}</th>
|
||||
|
||||
<th className='lft sortable' onMouseOver={termtip.bind(null, 'TT_EFFECTIVE_SDPS_ARMOUR')} onMouseOut={tooltip.bind(null, null)}onClick={sortOrder.bind(this, 'esdpsh')}>{'sdps'}</th>
|
||||
<th className='sortable' onMouseOver={termtip.bind(null, 'TT_EFFECTIVENESS_ARMOUR')} onMouseOut={tooltip.bind(null, null)}onClick={sortOrder.bind(this, 'eh')}>{'eft'}</th>
|
||||
|
||||
<th className='sortable'>{'dpe'}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@@ -290,8 +300,10 @@ export default class Offence extends TranslatedComponent {
|
||||
<td className='ri'><span onMouseOver={termtip.bind(null, totalSDpsTooltipDetails)} onMouseOut={tooltip.bind(null, null)}>={formats.f1(totalSDps)}</span></td>
|
||||
<td className='ri'><span onMouseOver={termtip.bind(null, totalShieldsSDpsTooltipDetails)} onMouseOut={tooltip.bind(null, null)}>={formats.f1(totalShieldsSDps)}</span></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td className='ri'><span onMouseOver={termtip.bind(null, totalArmourSDpsTooltipDetails)} onMouseOut={tooltip.bind(null, null)}>={formats.f1(totalArmourSDps)}</span></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
|
||||
@@ -205,7 +205,7 @@
|
||||
"internal protection": "Internal protection",
|
||||
"external protection": "External protection",
|
||||
"engagement range": "Engagement range",
|
||||
"boost interval": "Boost intervall",
|
||||
"boost interval": "Boost interval",
|
||||
"total": "Total",
|
||||
"ammo": "Ammunition maximum",
|
||||
"boot": "Boot time",
|
||||
|
||||
@@ -165,12 +165,12 @@
|
||||
"external protection": "Внешняя защита",
|
||||
"engagement range": "Боевое расстояние",
|
||||
"total": "Всего",
|
||||
"ammo": "Боекомплект",
|
||||
"ammo": "Макс. боекомплект",
|
||||
"boot": "Время загрузки",
|
||||
"brokenregen": "Скорость восстановления при пробое",
|
||||
"burst": "Длина очереди",
|
||||
"burstrof": "Скорострельность очереди",
|
||||
"clip": "Боекомплект",
|
||||
"clip": "Размер боекомплекта",
|
||||
"damage": "Урон",
|
||||
"distdraw": "Тяга распределителя",
|
||||
"duration": "Продолжительность",
|
||||
|
||||
@@ -94,39 +94,6 @@ export default class AboutPage extends Page {
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
|
||||
<h3>Supporting Coriolis</h3>
|
||||
<p>
|
||||
Coriolis is an open source project, and I work on it in my free time.
|
||||
I have set up a patreon at{' '}
|
||||
<a href="https://www.patreon.com/coriolis_elite">
|
||||
patreon.com/coriolis_elite
|
||||
</a>
|
||||
, which will be used to keep Coriolis up to date and the servers
|
||||
running.
|
||||
</p>
|
||||
<form
|
||||
action="https://www.paypal.com/cgi-bin/webscr"
|
||||
method="post"
|
||||
target="_top"
|
||||
>
|
||||
<input type="hidden" name="cmd" value="_s-xclick" />
|
||||
<input type="hidden" name="hosted_button_id" value="SJBKT2SWEEU68" />
|
||||
<input
|
||||
type="image"
|
||||
src="https://www.paypalobjects.com/en_AU/i/btn/btn_donate_SM.gif"
|
||||
border="0"
|
||||
name="submit"
|
||||
alt="PayPal – The safer, easier way to pay online!"
|
||||
/>
|
||||
<img
|
||||
alt=""
|
||||
border="0"
|
||||
src="https://www.paypalobjects.com/en_AU/i/scr/pixel.gif"
|
||||
width="1"
|
||||
height="1"
|
||||
/>
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -686,13 +686,12 @@ export default class OutfittingPage extends Page {
|
||||
_genOrbis() {
|
||||
const data = {};
|
||||
const ship = this.state.ship;
|
||||
ship.coriolisId = ship.id;
|
||||
data.coriolisShip = ship;
|
||||
data.url = window.location.href;
|
||||
data.title = this.state.buildName || ship.id;
|
||||
data.description = this.state.buildName || ship.id;
|
||||
data.ShipName = ship.id;
|
||||
data.Ship = ship.id;
|
||||
data.body = ship;
|
||||
data.url = `https://coriolis.io${outfitURL(ship.id, ship.toString(), data.title)}`;
|
||||
ship.type = ship.id;
|
||||
|
||||
console.log(data);
|
||||
this.context.showModal(<ModalOrbis ship={data} />);
|
||||
}
|
||||
|
||||
@@ -62,6 +62,14 @@ export default class Page extends React.Component {
|
||||
*/
|
||||
componentDidMount() {
|
||||
document.title = this.state.title || 'Coriolis';
|
||||
try {
|
||||
(window.adsbygoogle = window.adsbygoogle || []).push({
|
||||
google_ad_client: "ca-pub-3709458261881414",
|
||||
enable_page_level_ads: true
|
||||
});
|
||||
} catch (error) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -14,6 +14,7 @@ export function jumpRange(mass, fsd, fuel, ship) {
|
||||
const fsdOptimalMass = fsd instanceof Module ? fsd.getOptMass() : fsd.optmass;
|
||||
let jumpAddition = 0;
|
||||
if (ship) {
|
||||
mass += ship.reserveFuelCapacity || 0;
|
||||
for (const module of ship.internal) {
|
||||
if (module && module.m && module.m.grp === 'gfsb' && ship.getSlotStatus(module) == 3) {
|
||||
jumpAddition += module.m.getJumpBoost();
|
||||
@@ -355,9 +356,6 @@ export function shieldMetrics(ship, sys) {
|
||||
let boosterExplDmg = 1;
|
||||
let boosterKinDmg = 1;
|
||||
let boosterThermDmg = 1;
|
||||
// const explDim = dimReturnLine(shieldGenerator.explres);
|
||||
// const thermDim = dimReturnLine(shieldGenerator.thermres);
|
||||
// const kinDim = dimReturnLine(shieldGenerator.kinres);
|
||||
for (let slot of ship.hardpoints) {
|
||||
if (slot.enabled && slot.m && slot.m.grp == 'sb') {
|
||||
boost += slot.m.getShieldBoost();
|
||||
@@ -368,35 +366,14 @@ export function shieldMetrics(ship, sys) {
|
||||
boosterKinDmg = boosterKinDmg * (1 - slot.m.getKineticResistance());
|
||||
boosterThermDmg = boosterThermDmg * (1 - slot.m.getThermalResistance());
|
||||
}
|
||||
if (slot.m && slot.m.grp == 'gsrp') {
|
||||
|
||||
}
|
||||
}
|
||||
// Calculate diminishing returns for boosters
|
||||
// Diminishing returns not currently in-game
|
||||
// boost = Math.min(boost, (1 - Math.pow(Math.E, -0.7 * boost)) * 2.5);
|
||||
|
||||
|
||||
// Remove base shield generator strength
|
||||
boost -= 1;
|
||||
|
||||
// if (res.expl > explDim) {
|
||||
// const overage = (res.expl - explDim) * 0.5;
|
||||
// res.expl = explDim + overage;
|
||||
// boosterExplDmg = explDim + overage;
|
||||
// }
|
||||
//
|
||||
// if (res.therm > thermDim) {
|
||||
// const overage = (res.therm - thermDim) * 0.5;
|
||||
// res.therm = thermDim + overage;
|
||||
// boosterThermDmg = thermDim + overage;
|
||||
// }
|
||||
//
|
||||
// if (res.kin > kinDim) {
|
||||
// const overage = (res.kin - kinDim) * 0.5;
|
||||
// res.kin = kinDim + overage;
|
||||
// boosterKinDmg = kinDim + overage;
|
||||
// }
|
||||
let shieldAddition = 0;
|
||||
if (ship) {
|
||||
for (const module of ship.internal) {
|
||||
@@ -498,7 +475,7 @@ export function shieldMetrics(ship, sys) {
|
||||
*/
|
||||
|
||||
let sgExplosiveDmg = 1 - shieldGenerator.getExplosiveResistance();
|
||||
let sgSbExplosiveDmg = diminishDamageMult(sgExplosiveDmg * 0.7, (1 - shieldGenerator.getExplosiveResistance()) * boosterExplDmg);
|
||||
let sgSbExplosiveDmg = diminishingReturnsShields(sgExplosiveDmg, sgExplosiveDmg * boosterExplDmg);
|
||||
/** @type {ShieldDamageMults} */
|
||||
shield.explosive = {
|
||||
generator: sgExplosiveDmg,
|
||||
@@ -510,7 +487,7 @@ export function shieldMetrics(ship, sys) {
|
||||
};
|
||||
|
||||
let sgKineticDmg = 1 - shieldGenerator.getKineticResistance();
|
||||
let sgSbKineticDmg = diminishDamageMult(sgKineticDmg * 0.7, (1 - shieldGenerator.getKineticResistance()) * boosterKinDmg);
|
||||
let sgSbKineticDmg = diminishingReturnsShields(sgKineticDmg, sgKineticDmg * boosterKinDmg);
|
||||
/** @type {ShieldDamageMults} */
|
||||
shield.kinetic = {
|
||||
generator: sgKineticDmg,
|
||||
@@ -522,7 +499,7 @@ export function shieldMetrics(ship, sys) {
|
||||
};
|
||||
|
||||
let sgThermalDmg = 1 - shieldGenerator.getThermalResistance();
|
||||
let sgSbThermalDmg = diminishDamageMult(sgThermalDmg * 0.7, (1 - shieldGenerator.getThermalResistance()) * boosterThermDmg);
|
||||
let sgSbThermalDmg = diminishingReturnsShields(sgThermalDmg , sgThermalDmg * boosterThermDmg);
|
||||
/** @type {ShieldDamageMults} */
|
||||
shield.thermal = {
|
||||
generator: sgThermalDmg,
|
||||
@@ -562,16 +539,10 @@ export function armourMetrics(ship) {
|
||||
let moduleArmour = 0;
|
||||
let moduleProtection = 1;
|
||||
const bulkheads = ship.bulkheads.m;
|
||||
let hullExplDmg = 1;
|
||||
let hullKinDmg = 1;
|
||||
let hullThermDmg = 1;
|
||||
let hullCausDmg = 1;
|
||||
// const dimReturnLine = (res) => 1 - (1 - res) * 0.7;
|
||||
// let res = {
|
||||
// kin: 0,
|
||||
// therm: 0,
|
||||
// expl: 0
|
||||
// };
|
||||
let hullExplDmgs = [];
|
||||
let hullKinDmgs = [];
|
||||
let hullThermDmgs = [];
|
||||
let hullCausDmgs = [];
|
||||
// Armour from HRPs and module armour from MRPs
|
||||
for (let slot of ship.internal) {
|
||||
if (slot.m && slot.enabled && (slot.m.grp === 'hr' || slot.m.grp === 'ghrp' || slot.m.grp == 'mahr')) {
|
||||
@@ -581,10 +552,10 @@ export function armourMetrics(ship) {
|
||||
// res.expl += slot.m.getExplosiveResistance();
|
||||
// res.kin += slot.m.getKineticResistance();
|
||||
// res.therm += slot.m.getThermalResistance();
|
||||
hullExplDmg = hullExplDmg * (1 - slot.m.getExplosiveResistance());
|
||||
hullKinDmg = hullKinDmg * (1 - slot.m.getKineticResistance());
|
||||
hullThermDmg = hullThermDmg * (1 - slot.m.getThermalResistance());
|
||||
hullCausDmg = hullCausDmg * (1 - slot.m.getCausticResistance());
|
||||
hullExplDmgs.push(1 - slot.m.getExplosiveResistance());
|
||||
hullKinDmgs.push(1 - slot.m.getKineticResistance());
|
||||
hullThermDmgs.push(1 - slot.m.getThermalResistance());
|
||||
hullCausDmgs.push(1 - slot.m.getCausticResistance());
|
||||
}
|
||||
if (slot.m && slot.enabled && (slot.m.grp == 'mrp' || slot.m.grp == 'gmrp')) {
|
||||
moduleArmour += slot.m.getIntegrity();
|
||||
@@ -593,27 +564,6 @@ export function armourMetrics(ship) {
|
||||
}
|
||||
moduleProtection = 1 - moduleProtection;
|
||||
|
||||
// const explDim = dimReturnLine(bulkheads.explres);
|
||||
// const thermDim = dimReturnLine(bulkheads.thermres);
|
||||
// const kinDim = dimReturnLine(bulkheads.kinres);
|
||||
// if (res.expl > explDim) {
|
||||
// const overage = (res.expl - explDim) * 0.5;
|
||||
// res.expl = explDim + overage;
|
||||
// hullExplDmg = explDim + overage;
|
||||
// }
|
||||
//
|
||||
// if (res.therm > thermDim) {
|
||||
// const overage = (res.therm - thermDim) * 0.5;
|
||||
// res.therm = thermDim + overage;
|
||||
// hullThermDmg = thermDim + overage;
|
||||
// }
|
||||
//
|
||||
// if (res.kin > kinDim) {
|
||||
// const overage = (res.kin - kinDim) * 0.5;
|
||||
// res.kin = kinDim + overage;
|
||||
// hullKinDmg = kinDim + overage;
|
||||
// }
|
||||
|
||||
const armour = {
|
||||
bulkheads: armourBulkheads,
|
||||
reinforcement: armourReinforcement,
|
||||
@@ -630,8 +580,8 @@ export function armourMetrics(ship) {
|
||||
total: 1
|
||||
};
|
||||
|
||||
let armourExplDmg = diminishDamageMult(0.7, 1 - ship.bulkheads.m.getExplosiveResistance());
|
||||
let armourReinforcedExplDmg = diminishDamageMult(0.7, (1 - ship.bulkheads.m.getExplosiveResistance()) * hullExplDmg);
|
||||
let armourExplDmg = 1 - ship.bulkheads.m.getExplosiveResistance();
|
||||
let armourReinforcedExplDmg = diminishingReturnsArmour(armourExplDmg, ...hullExplDmgs);
|
||||
armour.explosive = {
|
||||
bulkheads: armourExplDmg,
|
||||
reinforcement: armourReinforcedExplDmg / armourExplDmg,
|
||||
@@ -639,8 +589,8 @@ export function armourMetrics(ship) {
|
||||
res: 1 - armourReinforcedExplDmg
|
||||
};
|
||||
|
||||
let armourKinDmg = diminishDamageMult(0.7, 1 - ship.bulkheads.m.getKineticResistance());
|
||||
let armourReinforcedKinDmg = diminishDamageMult(0.7, (1 - ship.bulkheads.m.getKineticResistance()) * hullKinDmg);
|
||||
let armourKinDmg = 1 - ship.bulkheads.m.getKineticResistance();
|
||||
let armourReinforcedKinDmg = diminishingReturnsArmour(armourKinDmg, ...hullKinDmgs);
|
||||
armour.kinetic = {
|
||||
bulkheads: armourKinDmg,
|
||||
reinforcement: armourReinforcedKinDmg / armourKinDmg,
|
||||
@@ -648,8 +598,8 @@ export function armourMetrics(ship) {
|
||||
res: 1 - armourReinforcedKinDmg
|
||||
};
|
||||
|
||||
let armourThermDmg = diminishDamageMult(0.7, 1 - ship.bulkheads.m.getThermalResistance());
|
||||
let armourReinforcedThermDmg = diminishDamageMult(0.7, (1 - ship.bulkheads.m.getThermalResistance()) * hullThermDmg);
|
||||
let armourThermDmg = 1 - ship.bulkheads.m.getThermalResistance();
|
||||
let armourReinforcedThermDmg = diminishingReturnsArmour(armourThermDmg, ...hullThermDmgs);
|
||||
armour.thermal = {
|
||||
bulkheads: armourThermDmg,
|
||||
reinforcement: armourReinforcedThermDmg / armourThermDmg,
|
||||
@@ -657,8 +607,8 @@ export function armourMetrics(ship) {
|
||||
res: 1 - armourReinforcedThermDmg
|
||||
};
|
||||
|
||||
let armourCausDmg = diminishDamageMult(0.7, 1 - ship.bulkheads.m.getCausticResistance());
|
||||
let armourReinforcedCausDmg = diminishDamageMult(0.7, (1 - ship.bulkheads.m.getCausticResistance()) * hullCausDmg);
|
||||
let armourCausDmg = 1 - ship.bulkheads.m.getCausticResistance();
|
||||
let armourReinforcedCausDmg = diminishingReturnsArmour(armourCausDmg, ...hullCausDmgs);
|
||||
armour.caustic = {
|
||||
bulkheads: armourCausDmg,
|
||||
reinforcement: armourReinforcedCausDmg / armourCausDmg,
|
||||
@@ -904,12 +854,14 @@ export function _weaponSustainedDps(m, opponent, opponentShields, opponentArmour
|
||||
shields: {
|
||||
range: 1,
|
||||
sys: opponentHasShields ? opponentShields.absolute.sys : 1,
|
||||
resistance: 1
|
||||
resistance: 1,
|
||||
dpe: 1
|
||||
},
|
||||
armour: {
|
||||
range: 1,
|
||||
hardness: 1,
|
||||
resistance: 1
|
||||
resistance: 1,
|
||||
dpe: 1
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -969,11 +921,19 @@ export function _weaponSustainedDps(m, opponent, opponentShields, opponentArmour
|
||||
weapon.damage.shields.total = weapon.damage.shields.absolute + weapon.damage.shields.explosive + weapon.damage.shields.kinetic + weapon.damage.shields.thermal;
|
||||
weapon.damage.armour.total = weapon.damage.armour.absolute + weapon.damage.armour.explosive + weapon.damage.armour.kinetic + weapon.damage.armour.thermal;
|
||||
|
||||
|
||||
|
||||
weapon.effectiveness.shields.resistance *= shieldsResistance;
|
||||
weapon.effectiveness.armour.resistance *= armourResistance;
|
||||
|
||||
|
||||
weapon.effectiveness.shields.total = weapon.effectiveness.shields.range * weapon.effectiveness.shields.sys * weapon.effectiveness.shields.resistance;
|
||||
weapon.effectiveness.armour.total = weapon.effectiveness.armour.range * weapon.effectiveness.armour.resistance * weapon.effectiveness.armour.hardness;
|
||||
|
||||
weapon.effectiveness.shields.dpe = weapon.damage.shields.total / m.getEps();
|
||||
weapon.effectiveness.armour.dpe = weapon.damage.armour.total / m.getEps();
|
||||
|
||||
|
||||
return weapon;
|
||||
}
|
||||
|
||||
@@ -1037,15 +997,50 @@ export function timeToDeplete(amount, dps, eps, capacity, recharge) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies diminishing returns to resistances.
|
||||
* @param {number} diminishFrom The base resistance up to which no diminishing returns are applied.
|
||||
* @param {number} damageMult Resistance as damage multiplier
|
||||
* @returns {number} Actual damage multiplier
|
||||
* Checks whether diminishing returns should be applied to shield damage
|
||||
* multipliers and does so if necessary.
|
||||
* @param {number} shieldMult Damage multiplier of shield generator
|
||||
* @param {number} combinedMult Damage multiplier of shields and shield boosters
|
||||
* @returns {number} Overall damage multiplier
|
||||
*/
|
||||
export function diminishDamageMult(diminishFrom, damageMult) {
|
||||
if (damageMult > diminishFrom) {
|
||||
return damageMult;
|
||||
export function diminishingReturnsShields(shieldMult, combinedMult) {
|
||||
let max = shieldMult * 0.7;
|
||||
if (combinedMult < max) {
|
||||
return mapIntoDiminishingRange(max / 2, max, combinedMult);
|
||||
} else {
|
||||
return (diminishFrom / 2) + 0.5 * damageMult;
|
||||
return combinedMult;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether diminishing returns should be applied to armour damage
|
||||
* multipliers and does so if necessary.
|
||||
* @param {...any} mults Damage multipliers of alloys and hull reinforcement
|
||||
* packages
|
||||
* @returns {number} Overall damage multiplier
|
||||
*/
|
||||
export function diminishingReturnsArmour(...mults) {
|
||||
let max = Math.min(0.7, ...mults);
|
||||
let combined = mults.reduce((aggr, v) => aggr * v);
|
||||
let diminished = mapIntoDiminishingRange(0.35, max, combined);
|
||||
if (diminished < 0.7) {
|
||||
return diminished;
|
||||
} else {
|
||||
return combined;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies diminishing returns to a damage multiplier. Effictively, the range
|
||||
* [`0`, `max`]` is mapped into the range [`min`, `max`] for the value `now`.
|
||||
* It can also happen, that `now` is outside of the range [`min`, `max`], then
|
||||
* `now` is actually improved, i.e. enlarged.
|
||||
* @param {number} min Best theoretical damage multiplier
|
||||
* @param {number} max Damage multiplier from which diminishing returns start to
|
||||
* be applied
|
||||
* @param {number} now The current damage multiplier
|
||||
* @returns {number} Remapped damage multiplier
|
||||
*/
|
||||
export function mapIntoDiminishingRange(min, max, now) {
|
||||
return min + (max - min) * (now / max);
|
||||
}
|
||||
|
||||
@@ -694,7 +694,7 @@ export default class Module {
|
||||
let result = 0;
|
||||
if (this['maxmass']) {
|
||||
result = this['maxmass'];
|
||||
if (result && modified) {
|
||||
if (result && modified && !ModuleUtils.isShieldGenerator(this['grp'])) {
|
||||
let mult = this.getModValue('optmass') / 10000;
|
||||
if (mult) { result = result * (1 + mult); }
|
||||
}
|
||||
|
||||
@@ -105,7 +105,7 @@ function orbisShorten(url, success, error) {
|
||||
}
|
||||
}
|
||||
|
||||
const API_ORBIS = 'https://orbis.zone/api/builds/add';
|
||||
const API_ORBIS = 'https://api.orbis.zone/ships';
|
||||
/**
|
||||
* Upload to Orbis
|
||||
* @param {object} ship The URL to shorten
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
<meta name="description" content="A ship builder, outfitting and comparison
|
||||
tool for Elite Dangerous">
|
||||
<meta name="mobile-web-app-capable" content="yes">
|
||||
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0,
|
||||
maximum-scale=1.0, user-scalable=0">
|
||||
<link rel="manifest" href="/manifest.json">
|
||||
@@ -25,7 +27,7 @@
|
||||
<meta name="msapplication-TileImage" content="/mstile-144x144.png">
|
||||
<meta name="msapplication-config" content="/browserconfig.xml">
|
||||
<meta name="theme-color" content="#000000">
|
||||
|
||||
<!-- <script data-ad-client="ca-pub-3709458261881414" async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script> -->
|
||||
<script>
|
||||
window.CORIOLIS_GAPI_KEY = '<%- htmlWebpackPlugin.options.gapiKey %>';
|
||||
window.CORIOLIS_VERSION = '<%- htmlWebpackPlugin.options.version %>';
|
||||
@@ -52,7 +54,8 @@
|
||||
</script>
|
||||
</head>
|
||||
<body style="background-color:#000;">
|
||||
<section id="coriolis"></section>
|
||||
<section id="coriolis">
|
||||
|
||||
</section>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
104
src/migrate.html
Normal file
104
src/migrate.html
Normal file
@@ -0,0 +1,104 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>Coriolis EDCD Edition</title>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="stylesheet" href="<%= htmlWebpackPlugin.files.css[0] %>" />
|
||||
<!-- Standard headers -->
|
||||
<meta
|
||||
name="description"
|
||||
content="A ship builder, outfitting and comparison
|
||||
tool for Elite Dangerous"
|
||||
/>
|
||||
<meta name="mobile-web-app-capable" content="yes" />
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1.0,
|
||||
maximum-scale=1.0, user-scalable=0"
|
||||
/>
|
||||
<link rel="manifest" href="/manifest.json" />
|
||||
<link rel="shortcut icon" href=/favicon2.ico>
|
||||
<link
|
||||
rel="icon"
|
||||
sizes="152x152 192x192"
|
||||
type="image/png"
|
||||
href="/192x192.png"
|
||||
/>
|
||||
<!-- Bugsnag -->
|
||||
<script src="https://d2wy8f7a9ursnm.cloudfront.net/v5.0.0/bugsnag.min.js"></script>
|
||||
<script>
|
||||
window.bugsnagClient = bugsnag('ba9fae819372850fb660755341fa6ef5', {appVersion: window.BUGSNAG_VERSION || undefined})
|
||||
window.Bugsnag = window.bugsnagClient
|
||||
</script>
|
||||
|
||||
<!-- Apple/iOS headers -->
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<meta name="apple-mobile-web-app-title" content="Coriolis" />
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
|
||||
|
||||
<!-- Microsoft Windows Phone/Tablet headers -->
|
||||
<meta name="msapplication-TileColor" content="#000000" />
|
||||
<meta name="msapplication-TileImage" content="/mstile-144x144.png" />
|
||||
<meta name="msapplication-config" content="/browserconfig.xml" />
|
||||
<meta name="theme-color" content="#000000" />
|
||||
</head>
|
||||
<body>
|
||||
<body style="background-color:#000;">
|
||||
<section id="coriolis">
|
||||
<div class="modal">
|
||||
<h2>
|
||||
Please migrate to <a href="https://coriolis.io">coriolis.io</a>
|
||||
</h2>
|
||||
You are currently on coriolis.<strong>.edcd</strong>.io This domain is
|
||||
considered deprecated. To migrate your builds, copy the below text and
|
||||
go to
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
href="https://coriolis.io"
|
||||
>this link</a
|
||||
>, press ctrl + i and then paste in the data. (If you are on mobile,
|
||||
you can go to the settings and hit import)
|
||||
<div>
|
||||
<textarea id="data" class="cb json"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</body>
|
||||
<script>
|
||||
const LS = localStorage;
|
||||
/**
|
||||
* Safe localstorage get string
|
||||
* @param {String} key key
|
||||
* @return {String} The stored string
|
||||
*/
|
||||
function _getString(key) {
|
||||
return LS ? LS.getItem(key) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Safe localstorage get
|
||||
* @param {String} key key
|
||||
* @return {object | number} The stored data
|
||||
*/
|
||||
function _get(key) {
|
||||
let str = _getString(key);
|
||||
try {
|
||||
return str ? JSON.parse(str) : null;
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
const textarea = document.querySelector("#data");
|
||||
const data = {
|
||||
builds: _get("builds") || {},
|
||||
comparisons: _get("comparisons") || {},
|
||||
insurance: _get("insurance") || "standard",
|
||||
shipDiscount: _get("shipDiscount") || 0,
|
||||
moduleDiscount: _get("moduleDiscount") || 0
|
||||
};
|
||||
textarea.textContent = JSON.stringify(data, null, 2);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user