diff --git a/css/dev-menu.css b/css/dev-menu.css
new file mode 100644
index 000000000..21a93e78b
--- /dev/null
+++ b/css/dev-menu.css
@@ -0,0 +1,36 @@
+.add-exp-button {
+ margin-right: 0px;
+}
+
+.remove-exp-button {
+ margin-left:0px;
+}
+
+.exp-input {
+ margin-right: 0px;
+ margin-left:0px;
+
+ margin-top: 5px;
+ margin-bottom: 5px;
+
+ padding: 2px 5px;
+}
+
+.text-center {
+ margin: auto;
+ text-align: center;
+ vertical-align: middle;
+}
+
+.touch-right {
+ margin-right: 0px;
+}
+
+.touch-left {
+ margin-left: 0px;
+}
+
+.touch-sides {
+ margin-left: 0px;
+ margin-right: 0px;
+}
\ No newline at end of file
diff --git a/css/grid.min.css b/css/grid.min.css
new file mode 100644
index 000000000..d617299c5
--- /dev/null
+++ b/css/grid.min.css
@@ -0,0 +1,6 @@
+/*!
+ * Bootstrap Grid v4.1.2 (https://getbootstrap.com/)
+ * Copyright 2011-2018 The Bootstrap Authors
+ * Copyright 2011-2018 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ */@-ms-viewport{width:device-width}html{-webkit-box-sizing:border-box;box-sizing:border-box;-ms-overflow-style:scrollbar}*,*::before,*::after{-webkit-box-sizing:inherit;box-sizing:inherit}.container{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width: 576px){.container{max-width:540px}}@media (min-width: 768px){.container{max-width:720px}}@media (min-width: 992px){.container{max-width:960px}}@media (min-width: 1200px){.container{max-width:1140px}}.container-fluid{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.row{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:-15px;margin-left:-15px}.no-gutters{margin-right:0;margin-left:0}.no-gutters>.col,.no-gutters>[class*="col-"]{padding-right:0;padding-left:0}.col-1,.col-2,.col-3,.col-4,.col-5,.col-6,.col-7,.col-8,.col-9,.col-10,.col-11,.col-12,.col,.col-auto,.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm,.col-sm-auto,.col-md-1,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-10,.col-md-11,.col-md-12,.col-md,.col-md-auto,.col-lg-1,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg,.col-lg-auto,.col-xl-1,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl,.col-xl-auto{position:relative;width:100%;min-height:1px;padding-right:15px;padding-left:15px}.col{-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-auto{-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-1{-webkit-box-flex:0;-ms-flex:0 0 8.3333333333%;flex:0 0 8.3333333333%;max-width:8.3333333333%}.col-2{-webkit-box-flex:0;-ms-flex:0 0 16.6666666667%;flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-3{-webkit-box-flex:0;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-4{-webkit-box-flex:0;-ms-flex:0 0 33.3333333333%;flex:0 0 33.3333333333%;max-width:33.3333333333%}.col-5{-webkit-box-flex:0;-ms-flex:0 0 41.6666666667%;flex:0 0 41.6666666667%;max-width:41.6666666667%}.col-6{-webkit-box-flex:0;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-7{-webkit-box-flex:0;-ms-flex:0 0 58.3333333333%;flex:0 0 58.3333333333%;max-width:58.3333333333%}.col-8{-webkit-box-flex:0;-ms-flex:0 0 66.6666666667%;flex:0 0 66.6666666667%;max-width:66.6666666667%}.col-9{-webkit-box-flex:0;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-10{-webkit-box-flex:0;-ms-flex:0 0 83.3333333333%;flex:0 0 83.3333333333%;max-width:83.3333333333%}.col-11{-webkit-box-flex:0;-ms-flex:0 0 91.6666666667%;flex:0 0 91.6666666667%;max-width:91.6666666667%}.col-12{-webkit-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-first{-webkit-box-ordinal-group:0;-ms-flex-order:-1;order:-1}.order-last{-webkit-box-ordinal-group:14;-ms-flex-order:13;order:13}.order-0{-webkit-box-ordinal-group:1;-ms-flex-order:0;order:0}.order-1{-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1}.order-2{-webkit-box-ordinal-group:3;-ms-flex-order:2;order:2}.order-3{-webkit-box-ordinal-group:4;-ms-flex-order:3;order:3}.order-4{-webkit-box-ordinal-group:5;-ms-flex-order:4;order:4}.order-5{-webkit-box-ordinal-group:6;-ms-flex-order:5;order:5}.order-6{-webkit-box-ordinal-group:7;-ms-flex-order:6;order:6}.order-7{-webkit-box-ordinal-group:8;-ms-flex-order:7;order:7}.order-8{-webkit-box-ordinal-group:9;-ms-flex-order:8;order:8}.order-9{-webkit-box-ordinal-group:10;-ms-flex-order:9;order:9}.order-10{-webkit-box-ordinal-group:11;-ms-flex-order:10;order:10}.order-11{-webkit-box-ordinal-group:12;-ms-flex-order:11;order:11}.order-12{-webkit-box-ordinal-group:13;-ms-flex-order:12;order:12}.offset-1{margin-left:8.3333333333%}.offset-2{margin-left:16.6666666667%}.offset-3{margin-left:25%}.offset-4{margin-left:33.3333333333%}.offset-5{margin-left:41.6666666667%}.offset-6{margin-left:50%}.offset-7{margin-left:58.3333333333%}.offset-8{margin-left:66.6666666667%}.offset-9{margin-left:75%}.offset-10{margin-left:83.3333333333%}.offset-11{margin-left:91.6666666667%}@media (min-width: 576px){.col-sm{-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-sm-auto{-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-sm-1{-webkit-box-flex:0;-ms-flex:0 0 8.3333333333%;flex:0 0 8.3333333333%;max-width:8.3333333333%}.col-sm-2{-webkit-box-flex:0;-ms-flex:0 0 16.6666666667%;flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-sm-3{-webkit-box-flex:0;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-sm-4{-webkit-box-flex:0;-ms-flex:0 0 33.3333333333%;flex:0 0 33.3333333333%;max-width:33.3333333333%}.col-sm-5{-webkit-box-flex:0;-ms-flex:0 0 41.6666666667%;flex:0 0 41.6666666667%;max-width:41.6666666667%}.col-sm-6{-webkit-box-flex:0;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-sm-7{-webkit-box-flex:0;-ms-flex:0 0 58.3333333333%;flex:0 0 58.3333333333%;max-width:58.3333333333%}.col-sm-8{-webkit-box-flex:0;-ms-flex:0 0 66.6666666667%;flex:0 0 66.6666666667%;max-width:66.6666666667%}.col-sm-9{-webkit-box-flex:0;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-sm-10{-webkit-box-flex:0;-ms-flex:0 0 83.3333333333%;flex:0 0 83.3333333333%;max-width:83.3333333333%}.col-sm-11{-webkit-box-flex:0;-ms-flex:0 0 91.6666666667%;flex:0 0 91.6666666667%;max-width:91.6666666667%}.col-sm-12{-webkit-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-sm-first{-webkit-box-ordinal-group:0;-ms-flex-order:-1;order:-1}.order-sm-last{-webkit-box-ordinal-group:14;-ms-flex-order:13;order:13}.order-sm-0{-webkit-box-ordinal-group:1;-ms-flex-order:0;order:0}.order-sm-1{-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1}.order-sm-2{-webkit-box-ordinal-group:3;-ms-flex-order:2;order:2}.order-sm-3{-webkit-box-ordinal-group:4;-ms-flex-order:3;order:3}.order-sm-4{-webkit-box-ordinal-group:5;-ms-flex-order:4;order:4}.order-sm-5{-webkit-box-ordinal-group:6;-ms-flex-order:5;order:5}.order-sm-6{-webkit-box-ordinal-group:7;-ms-flex-order:6;order:6}.order-sm-7{-webkit-box-ordinal-group:8;-ms-flex-order:7;order:7}.order-sm-8{-webkit-box-ordinal-group:9;-ms-flex-order:8;order:8}.order-sm-9{-webkit-box-ordinal-group:10;-ms-flex-order:9;order:9}.order-sm-10{-webkit-box-ordinal-group:11;-ms-flex-order:10;order:10}.order-sm-11{-webkit-box-ordinal-group:12;-ms-flex-order:11;order:11}.order-sm-12{-webkit-box-ordinal-group:13;-ms-flex-order:12;order:12}.offset-sm-0{margin-left:0}.offset-sm-1{margin-left:8.3333333333%}.offset-sm-2{margin-left:16.6666666667%}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:33.3333333333%}.offset-sm-5{margin-left:41.6666666667%}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:58.3333333333%}.offset-sm-8{margin-left:66.6666666667%}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:83.3333333333%}.offset-sm-11{margin-left:91.6666666667%}}@media (min-width: 768px){.col-md{-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-md-auto{-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-md-1{-webkit-box-flex:0;-ms-flex:0 0 8.3333333333%;flex:0 0 8.3333333333%;max-width:8.3333333333%}.col-md-2{-webkit-box-flex:0;-ms-flex:0 0 16.6666666667%;flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-md-3{-webkit-box-flex:0;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-md-4{-webkit-box-flex:0;-ms-flex:0 0 33.3333333333%;flex:0 0 33.3333333333%;max-width:33.3333333333%}.col-md-5{-webkit-box-flex:0;-ms-flex:0 0 41.6666666667%;flex:0 0 41.6666666667%;max-width:41.6666666667%}.col-md-6{-webkit-box-flex:0;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-md-7{-webkit-box-flex:0;-ms-flex:0 0 58.3333333333%;flex:0 0 58.3333333333%;max-width:58.3333333333%}.col-md-8{-webkit-box-flex:0;-ms-flex:0 0 66.6666666667%;flex:0 0 66.6666666667%;max-width:66.6666666667%}.col-md-9{-webkit-box-flex:0;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-md-10{-webkit-box-flex:0;-ms-flex:0 0 83.3333333333%;flex:0 0 83.3333333333%;max-width:83.3333333333%}.col-md-11{-webkit-box-flex:0;-ms-flex:0 0 91.6666666667%;flex:0 0 91.6666666667%;max-width:91.6666666667%}.col-md-12{-webkit-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-md-first{-webkit-box-ordinal-group:0;-ms-flex-order:-1;order:-1}.order-md-last{-webkit-box-ordinal-group:14;-ms-flex-order:13;order:13}.order-md-0{-webkit-box-ordinal-group:1;-ms-flex-order:0;order:0}.order-md-1{-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1}.order-md-2{-webkit-box-ordinal-group:3;-ms-flex-order:2;order:2}.order-md-3{-webkit-box-ordinal-group:4;-ms-flex-order:3;order:3}.order-md-4{-webkit-box-ordinal-group:5;-ms-flex-order:4;order:4}.order-md-5{-webkit-box-ordinal-group:6;-ms-flex-order:5;order:5}.order-md-6{-webkit-box-ordinal-group:7;-ms-flex-order:6;order:6}.order-md-7{-webkit-box-ordinal-group:8;-ms-flex-order:7;order:7}.order-md-8{-webkit-box-ordinal-group:9;-ms-flex-order:8;order:8}.order-md-9{-webkit-box-ordinal-group:10;-ms-flex-order:9;order:9}.order-md-10{-webkit-box-ordinal-group:11;-ms-flex-order:10;order:10}.order-md-11{-webkit-box-ordinal-group:12;-ms-flex-order:11;order:11}.order-md-12{-webkit-box-ordinal-group:13;-ms-flex-order:12;order:12}.offset-md-0{margin-left:0}.offset-md-1{margin-left:8.3333333333%}.offset-md-2{margin-left:16.6666666667%}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:33.3333333333%}.offset-md-5{margin-left:41.6666666667%}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:58.3333333333%}.offset-md-8{margin-left:66.6666666667%}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:83.3333333333%}.offset-md-11{margin-left:91.6666666667%}}@media (min-width: 992px){.col-lg{-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-lg-auto{-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-lg-1{-webkit-box-flex:0;-ms-flex:0 0 8.3333333333%;flex:0 0 8.3333333333%;max-width:8.3333333333%}.col-lg-2{-webkit-box-flex:0;-ms-flex:0 0 16.6666666667%;flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-lg-3{-webkit-box-flex:0;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-lg-4{-webkit-box-flex:0;-ms-flex:0 0 33.3333333333%;flex:0 0 33.3333333333%;max-width:33.3333333333%}.col-lg-5{-webkit-box-flex:0;-ms-flex:0 0 41.6666666667%;flex:0 0 41.6666666667%;max-width:41.6666666667%}.col-lg-6{-webkit-box-flex:0;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-lg-7{-webkit-box-flex:0;-ms-flex:0 0 58.3333333333%;flex:0 0 58.3333333333%;max-width:58.3333333333%}.col-lg-8{-webkit-box-flex:0;-ms-flex:0 0 66.6666666667%;flex:0 0 66.6666666667%;max-width:66.6666666667%}.col-lg-9{-webkit-box-flex:0;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-lg-10{-webkit-box-flex:0;-ms-flex:0 0 83.3333333333%;flex:0 0 83.3333333333%;max-width:83.3333333333%}.col-lg-11{-webkit-box-flex:0;-ms-flex:0 0 91.6666666667%;flex:0 0 91.6666666667%;max-width:91.6666666667%}.col-lg-12{-webkit-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-lg-first{-webkit-box-ordinal-group:0;-ms-flex-order:-1;order:-1}.order-lg-last{-webkit-box-ordinal-group:14;-ms-flex-order:13;order:13}.order-lg-0{-webkit-box-ordinal-group:1;-ms-flex-order:0;order:0}.order-lg-1{-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1}.order-lg-2{-webkit-box-ordinal-group:3;-ms-flex-order:2;order:2}.order-lg-3{-webkit-box-ordinal-group:4;-ms-flex-order:3;order:3}.order-lg-4{-webkit-box-ordinal-group:5;-ms-flex-order:4;order:4}.order-lg-5{-webkit-box-ordinal-group:6;-ms-flex-order:5;order:5}.order-lg-6{-webkit-box-ordinal-group:7;-ms-flex-order:6;order:6}.order-lg-7{-webkit-box-ordinal-group:8;-ms-flex-order:7;order:7}.order-lg-8{-webkit-box-ordinal-group:9;-ms-flex-order:8;order:8}.order-lg-9{-webkit-box-ordinal-group:10;-ms-flex-order:9;order:9}.order-lg-10{-webkit-box-ordinal-group:11;-ms-flex-order:10;order:10}.order-lg-11{-webkit-box-ordinal-group:12;-ms-flex-order:11;order:11}.order-lg-12{-webkit-box-ordinal-group:13;-ms-flex-order:12;order:12}.offset-lg-0{margin-left:0}.offset-lg-1{margin-left:8.3333333333%}.offset-lg-2{margin-left:16.6666666667%}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:33.3333333333%}.offset-lg-5{margin-left:41.6666666667%}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:58.3333333333%}.offset-lg-8{margin-left:66.6666666667%}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:83.3333333333%}.offset-lg-11{margin-left:91.6666666667%}}@media (min-width: 1200px){.col-xl{-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-xl-auto{-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-xl-1{-webkit-box-flex:0;-ms-flex:0 0 8.3333333333%;flex:0 0 8.3333333333%;max-width:8.3333333333%}.col-xl-2{-webkit-box-flex:0;-ms-flex:0 0 16.6666666667%;flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-xl-3{-webkit-box-flex:0;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-xl-4{-webkit-box-flex:0;-ms-flex:0 0 33.3333333333%;flex:0 0 33.3333333333%;max-width:33.3333333333%}.col-xl-5{-webkit-box-flex:0;-ms-flex:0 0 41.6666666667%;flex:0 0 41.6666666667%;max-width:41.6666666667%}.col-xl-6{-webkit-box-flex:0;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-xl-7{-webkit-box-flex:0;-ms-flex:0 0 58.3333333333%;flex:0 0 58.3333333333%;max-width:58.3333333333%}.col-xl-8{-webkit-box-flex:0;-ms-flex:0 0 66.6666666667%;flex:0 0 66.6666666667%;max-width:66.6666666667%}.col-xl-9{-webkit-box-flex:0;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-xl-10{-webkit-box-flex:0;-ms-flex:0 0 83.3333333333%;flex:0 0 83.3333333333%;max-width:83.3333333333%}.col-xl-11{-webkit-box-flex:0;-ms-flex:0 0 91.6666666667%;flex:0 0 91.6666666667%;max-width:91.6666666667%}.col-xl-12{-webkit-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-xl-first{-webkit-box-ordinal-group:0;-ms-flex-order:-1;order:-1}.order-xl-last{-webkit-box-ordinal-group:14;-ms-flex-order:13;order:13}.order-xl-0{-webkit-box-ordinal-group:1;-ms-flex-order:0;order:0}.order-xl-1{-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1}.order-xl-2{-webkit-box-ordinal-group:3;-ms-flex-order:2;order:2}.order-xl-3{-webkit-box-ordinal-group:4;-ms-flex-order:3;order:3}.order-xl-4{-webkit-box-ordinal-group:5;-ms-flex-order:4;order:4}.order-xl-5{-webkit-box-ordinal-group:6;-ms-flex-order:5;order:5}.order-xl-6{-webkit-box-ordinal-group:7;-ms-flex-order:6;order:6}.order-xl-7{-webkit-box-ordinal-group:8;-ms-flex-order:7;order:7}.order-xl-8{-webkit-box-ordinal-group:9;-ms-flex-order:8;order:8}.order-xl-9{-webkit-box-ordinal-group:10;-ms-flex-order:9;order:9}.order-xl-10{-webkit-box-ordinal-group:11;-ms-flex-order:10;order:10}.order-xl-11{-webkit-box-ordinal-group:12;-ms-flex-order:11;order:11}.order-xl-12{-webkit-box-ordinal-group:13;-ms-flex-order:12;order:12}.offset-xl-0{margin-left:0}.offset-xl-1{margin-left:8.3333333333%}.offset-xl-2{margin-left:16.6666666667%}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:33.3333333333%}.offset-xl-5{margin-left:41.6666666667%}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:58.3333333333%}.offset-xl-8{margin-left:66.6666666667%}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:83.3333333333%}.offset-xl-11{margin-left:91.6666666667%}}.d-none{display:none !important}.d-inline{display:inline !important}.d-inline-block{display:inline-block !important}.d-block{display:block !important}.d-table{display:table !important}.d-table-row{display:table-row !important}.d-table-cell{display:table-cell !important}.d-flex{display:-webkit-box !important;display:-ms-flexbox !important;display:flex !important}.d-inline-flex{display:-webkit-inline-box !important;display:-ms-inline-flexbox !important;display:inline-flex !important}@media (min-width: 576px){.d-sm-none{display:none !important}.d-sm-inline{display:inline !important}.d-sm-inline-block{display:inline-block !important}.d-sm-block{display:block !important}.d-sm-table{display:table !important}.d-sm-table-row{display:table-row !important}.d-sm-table-cell{display:table-cell !important}.d-sm-flex{display:-webkit-box !important;display:-ms-flexbox !important;display:flex !important}.d-sm-inline-flex{display:-webkit-inline-box !important;display:-ms-inline-flexbox !important;display:inline-flex !important}}@media (min-width: 768px){.d-md-none{display:none !important}.d-md-inline{display:inline !important}.d-md-inline-block{display:inline-block !important}.d-md-block{display:block !important}.d-md-table{display:table !important}.d-md-table-row{display:table-row !important}.d-md-table-cell{display:table-cell !important}.d-md-flex{display:-webkit-box !important;display:-ms-flexbox !important;display:flex !important}.d-md-inline-flex{display:-webkit-inline-box !important;display:-ms-inline-flexbox !important;display:inline-flex !important}}@media (min-width: 992px){.d-lg-none{display:none !important}.d-lg-inline{display:inline !important}.d-lg-inline-block{display:inline-block !important}.d-lg-block{display:block !important}.d-lg-table{display:table !important}.d-lg-table-row{display:table-row !important}.d-lg-table-cell{display:table-cell !important}.d-lg-flex{display:-webkit-box !important;display:-ms-flexbox !important;display:flex !important}.d-lg-inline-flex{display:-webkit-inline-box !important;display:-ms-inline-flexbox !important;display:inline-flex !important}}@media (min-width: 1200px){.d-xl-none{display:none !important}.d-xl-inline{display:inline !important}.d-xl-inline-block{display:inline-block !important}.d-xl-block{display:block !important}.d-xl-table{display:table !important}.d-xl-table-row{display:table-row !important}.d-xl-table-cell{display:table-cell !important}.d-xl-flex{display:-webkit-box !important;display:-ms-flexbox !important;display:flex !important}.d-xl-inline-flex{display:-webkit-inline-box !important;display:-ms-inline-flexbox !important;display:inline-flex !important}}@media print{.d-print-none{display:none !important}.d-print-inline{display:inline !important}.d-print-inline-block{display:inline-block !important}.d-print-block{display:block !important}.d-print-table{display:table !important}.d-print-table-row{display:table-row !important}.d-print-table-cell{display:table-cell !important}.d-print-flex{display:-webkit-box !important;display:-ms-flexbox !important;display:flex !important}.d-print-inline-flex{display:-webkit-inline-box !important;display:-ms-inline-flexbox !important;display:inline-flex !important}}.flex-row{-webkit-box-orient:horizontal !important;-webkit-box-direction:normal !important;-ms-flex-direction:row !important;flex-direction:row !important}.flex-column{-webkit-box-orient:vertical !important;-webkit-box-direction:normal !important;-ms-flex-direction:column !important;flex-direction:column !important}.flex-row-reverse{-webkit-box-orient:horizontal !important;-webkit-box-direction:reverse !important;-ms-flex-direction:row-reverse !important;flex-direction:row-reverse !important}.flex-column-reverse{-webkit-box-orient:vertical !important;-webkit-box-direction:reverse !important;-ms-flex-direction:column-reverse !important;flex-direction:column-reverse !important}.flex-wrap{-ms-flex-wrap:wrap !important;flex-wrap:wrap !important}.flex-nowrap{-ms-flex-wrap:nowrap !important;flex-wrap:nowrap !important}.flex-wrap-reverse{-ms-flex-wrap:wrap-reverse !important;flex-wrap:wrap-reverse !important}.flex-fill{-webkit-box-flex:1 !important;-ms-flex:1 1 auto !important;flex:1 1 auto !important}.flex-grow-0{-webkit-box-flex:0 !important;-ms-flex-positive:0 !important;flex-grow:0 !important}.flex-grow-1{-webkit-box-flex:1 !important;-ms-flex-positive:1 !important;flex-grow:1 !important}.flex-shrink-0{-ms-flex-negative:0 !important;flex-shrink:0 !important}.flex-shrink-1{-ms-flex-negative:1 !important;flex-shrink:1 !important}.justify-content-start{-webkit-box-pack:start !important;-ms-flex-pack:start !important;justify-content:flex-start !important}.justify-content-end{-webkit-box-pack:end !important;-ms-flex-pack:end !important;justify-content:flex-end !important}.justify-content-center{-webkit-box-pack:center !important;-ms-flex-pack:center !important;justify-content:center !important}.justify-content-between{-webkit-box-pack:justify !important;-ms-flex-pack:justify !important;justify-content:space-between !important}.justify-content-around{-ms-flex-pack:distribute !important;justify-content:space-around !important}.align-items-start{-webkit-box-align:start !important;-ms-flex-align:start !important;align-items:flex-start !important}.align-items-end{-webkit-box-align:end !important;-ms-flex-align:end !important;align-items:flex-end !important}.align-items-center{-webkit-box-align:center !important;-ms-flex-align:center !important;align-items:center !important}.align-items-baseline{-webkit-box-align:baseline !important;-ms-flex-align:baseline !important;align-items:baseline !important}.align-items-stretch{-webkit-box-align:stretch !important;-ms-flex-align:stretch !important;align-items:stretch !important}.align-content-start{-ms-flex-line-pack:start !important;align-content:flex-start !important}.align-content-end{-ms-flex-line-pack:end !important;align-content:flex-end !important}.align-content-center{-ms-flex-line-pack:center !important;align-content:center !important}.align-content-between{-ms-flex-line-pack:justify !important;align-content:space-between !important}.align-content-around{-ms-flex-line-pack:distribute !important;align-content:space-around !important}.align-content-stretch{-ms-flex-line-pack:stretch !important;align-content:stretch !important}.align-self-auto{-ms-flex-item-align:auto !important;align-self:auto !important}.align-self-start{-ms-flex-item-align:start !important;align-self:flex-start !important}.align-self-end{-ms-flex-item-align:end !important;align-self:flex-end !important}.align-self-center{-ms-flex-item-align:center !important;align-self:center !important}.align-self-baseline{-ms-flex-item-align:baseline !important;align-self:baseline !important}.align-self-stretch{-ms-flex-item-align:stretch !important;align-self:stretch !important}@media (min-width: 576px){.flex-sm-row{-webkit-box-orient:horizontal !important;-webkit-box-direction:normal !important;-ms-flex-direction:row !important;flex-direction:row !important}.flex-sm-column{-webkit-box-orient:vertical !important;-webkit-box-direction:normal !important;-ms-flex-direction:column !important;flex-direction:column !important}.flex-sm-row-reverse{-webkit-box-orient:horizontal !important;-webkit-box-direction:reverse !important;-ms-flex-direction:row-reverse !important;flex-direction:row-reverse !important}.flex-sm-column-reverse{-webkit-box-orient:vertical !important;-webkit-box-direction:reverse !important;-ms-flex-direction:column-reverse !important;flex-direction:column-reverse !important}.flex-sm-wrap{-ms-flex-wrap:wrap !important;flex-wrap:wrap !important}.flex-sm-nowrap{-ms-flex-wrap:nowrap !important;flex-wrap:nowrap !important}.flex-sm-wrap-reverse{-ms-flex-wrap:wrap-reverse !important;flex-wrap:wrap-reverse !important}.flex-sm-fill{-webkit-box-flex:1 !important;-ms-flex:1 1 auto !important;flex:1 1 auto !important}.flex-sm-grow-0{-webkit-box-flex:0 !important;-ms-flex-positive:0 !important;flex-grow:0 !important}.flex-sm-grow-1{-webkit-box-flex:1 !important;-ms-flex-positive:1 !important;flex-grow:1 !important}.flex-sm-shrink-0{-ms-flex-negative:0 !important;flex-shrink:0 !important}.flex-sm-shrink-1{-ms-flex-negative:1 !important;flex-shrink:1 !important}.justify-content-sm-start{-webkit-box-pack:start !important;-ms-flex-pack:start !important;justify-content:flex-start !important}.justify-content-sm-end{-webkit-box-pack:end !important;-ms-flex-pack:end !important;justify-content:flex-end !important}.justify-content-sm-center{-webkit-box-pack:center !important;-ms-flex-pack:center !important;justify-content:center !important}.justify-content-sm-between{-webkit-box-pack:justify !important;-ms-flex-pack:justify !important;justify-content:space-between !important}.justify-content-sm-around{-ms-flex-pack:distribute !important;justify-content:space-around !important}.align-items-sm-start{-webkit-box-align:start !important;-ms-flex-align:start !important;align-items:flex-start !important}.align-items-sm-end{-webkit-box-align:end !important;-ms-flex-align:end !important;align-items:flex-end !important}.align-items-sm-center{-webkit-box-align:center !important;-ms-flex-align:center !important;align-items:center !important}.align-items-sm-baseline{-webkit-box-align:baseline !important;-ms-flex-align:baseline !important;align-items:baseline !important}.align-items-sm-stretch{-webkit-box-align:stretch !important;-ms-flex-align:stretch !important;align-items:stretch !important}.align-content-sm-start{-ms-flex-line-pack:start !important;align-content:flex-start !important}.align-content-sm-end{-ms-flex-line-pack:end !important;align-content:flex-end !important}.align-content-sm-center{-ms-flex-line-pack:center !important;align-content:center !important}.align-content-sm-between{-ms-flex-line-pack:justify !important;align-content:space-between !important}.align-content-sm-around{-ms-flex-line-pack:distribute !important;align-content:space-around !important}.align-content-sm-stretch{-ms-flex-line-pack:stretch !important;align-content:stretch !important}.align-self-sm-auto{-ms-flex-item-align:auto !important;align-self:auto !important}.align-self-sm-start{-ms-flex-item-align:start !important;align-self:flex-start !important}.align-self-sm-end{-ms-flex-item-align:end !important;align-self:flex-end !important}.align-self-sm-center{-ms-flex-item-align:center !important;align-self:center !important}.align-self-sm-baseline{-ms-flex-item-align:baseline !important;align-self:baseline !important}.align-self-sm-stretch{-ms-flex-item-align:stretch !important;align-self:stretch !important}}@media (min-width: 768px){.flex-md-row{-webkit-box-orient:horizontal !important;-webkit-box-direction:normal !important;-ms-flex-direction:row !important;flex-direction:row !important}.flex-md-column{-webkit-box-orient:vertical !important;-webkit-box-direction:normal !important;-ms-flex-direction:column !important;flex-direction:column !important}.flex-md-row-reverse{-webkit-box-orient:horizontal !important;-webkit-box-direction:reverse !important;-ms-flex-direction:row-reverse !important;flex-direction:row-reverse !important}.flex-md-column-reverse{-webkit-box-orient:vertical !important;-webkit-box-direction:reverse !important;-ms-flex-direction:column-reverse !important;flex-direction:column-reverse !important}.flex-md-wrap{-ms-flex-wrap:wrap !important;flex-wrap:wrap !important}.flex-md-nowrap{-ms-flex-wrap:nowrap !important;flex-wrap:nowrap !important}.flex-md-wrap-reverse{-ms-flex-wrap:wrap-reverse !important;flex-wrap:wrap-reverse !important}.flex-md-fill{-webkit-box-flex:1 !important;-ms-flex:1 1 auto !important;flex:1 1 auto !important}.flex-md-grow-0{-webkit-box-flex:0 !important;-ms-flex-positive:0 !important;flex-grow:0 !important}.flex-md-grow-1{-webkit-box-flex:1 !important;-ms-flex-positive:1 !important;flex-grow:1 !important}.flex-md-shrink-0{-ms-flex-negative:0 !important;flex-shrink:0 !important}.flex-md-shrink-1{-ms-flex-negative:1 !important;flex-shrink:1 !important}.justify-content-md-start{-webkit-box-pack:start !important;-ms-flex-pack:start !important;justify-content:flex-start !important}.justify-content-md-end{-webkit-box-pack:end !important;-ms-flex-pack:end !important;justify-content:flex-end !important}.justify-content-md-center{-webkit-box-pack:center !important;-ms-flex-pack:center !important;justify-content:center !important}.justify-content-md-between{-webkit-box-pack:justify !important;-ms-flex-pack:justify !important;justify-content:space-between !important}.justify-content-md-around{-ms-flex-pack:distribute !important;justify-content:space-around !important}.align-items-md-start{-webkit-box-align:start !important;-ms-flex-align:start !important;align-items:flex-start !important}.align-items-md-end{-webkit-box-align:end !important;-ms-flex-align:end !important;align-items:flex-end !important}.align-items-md-center{-webkit-box-align:center !important;-ms-flex-align:center !important;align-items:center !important}.align-items-md-baseline{-webkit-box-align:baseline !important;-ms-flex-align:baseline !important;align-items:baseline !important}.align-items-md-stretch{-webkit-box-align:stretch !important;-ms-flex-align:stretch !important;align-items:stretch !important}.align-content-md-start{-ms-flex-line-pack:start !important;align-content:flex-start !important}.align-content-md-end{-ms-flex-line-pack:end !important;align-content:flex-end !important}.align-content-md-center{-ms-flex-line-pack:center !important;align-content:center !important}.align-content-md-between{-ms-flex-line-pack:justify !important;align-content:space-between !important}.align-content-md-around{-ms-flex-line-pack:distribute !important;align-content:space-around !important}.align-content-md-stretch{-ms-flex-line-pack:stretch !important;align-content:stretch !important}.align-self-md-auto{-ms-flex-item-align:auto !important;align-self:auto !important}.align-self-md-start{-ms-flex-item-align:start !important;align-self:flex-start !important}.align-self-md-end{-ms-flex-item-align:end !important;align-self:flex-end !important}.align-self-md-center{-ms-flex-item-align:center !important;align-self:center !important}.align-self-md-baseline{-ms-flex-item-align:baseline !important;align-self:baseline !important}.align-self-md-stretch{-ms-flex-item-align:stretch !important;align-self:stretch !important}}@media (min-width: 992px){.flex-lg-row{-webkit-box-orient:horizontal !important;-webkit-box-direction:normal !important;-ms-flex-direction:row !important;flex-direction:row !important}.flex-lg-column{-webkit-box-orient:vertical !important;-webkit-box-direction:normal !important;-ms-flex-direction:column !important;flex-direction:column !important}.flex-lg-row-reverse{-webkit-box-orient:horizontal !important;-webkit-box-direction:reverse !important;-ms-flex-direction:row-reverse !important;flex-direction:row-reverse !important}.flex-lg-column-reverse{-webkit-box-orient:vertical !important;-webkit-box-direction:reverse !important;-ms-flex-direction:column-reverse !important;flex-direction:column-reverse !important}.flex-lg-wrap{-ms-flex-wrap:wrap !important;flex-wrap:wrap !important}.flex-lg-nowrap{-ms-flex-wrap:nowrap !important;flex-wrap:nowrap !important}.flex-lg-wrap-reverse{-ms-flex-wrap:wrap-reverse !important;flex-wrap:wrap-reverse !important}.flex-lg-fill{-webkit-box-flex:1 !important;-ms-flex:1 1 auto !important;flex:1 1 auto !important}.flex-lg-grow-0{-webkit-box-flex:0 !important;-ms-flex-positive:0 !important;flex-grow:0 !important}.flex-lg-grow-1{-webkit-box-flex:1 !important;-ms-flex-positive:1 !important;flex-grow:1 !important}.flex-lg-shrink-0{-ms-flex-negative:0 !important;flex-shrink:0 !important}.flex-lg-shrink-1{-ms-flex-negative:1 !important;flex-shrink:1 !important}.justify-content-lg-start{-webkit-box-pack:start !important;-ms-flex-pack:start !important;justify-content:flex-start !important}.justify-content-lg-end{-webkit-box-pack:end !important;-ms-flex-pack:end !important;justify-content:flex-end !important}.justify-content-lg-center{-webkit-box-pack:center !important;-ms-flex-pack:center !important;justify-content:center !important}.justify-content-lg-between{-webkit-box-pack:justify !important;-ms-flex-pack:justify !important;justify-content:space-between !important}.justify-content-lg-around{-ms-flex-pack:distribute !important;justify-content:space-around !important}.align-items-lg-start{-webkit-box-align:start !important;-ms-flex-align:start !important;align-items:flex-start !important}.align-items-lg-end{-webkit-box-align:end !important;-ms-flex-align:end !important;align-items:flex-end !important}.align-items-lg-center{-webkit-box-align:center !important;-ms-flex-align:center !important;align-items:center !important}.align-items-lg-baseline{-webkit-box-align:baseline !important;-ms-flex-align:baseline !important;align-items:baseline !important}.align-items-lg-stretch{-webkit-box-align:stretch !important;-ms-flex-align:stretch !important;align-items:stretch !important}.align-content-lg-start{-ms-flex-line-pack:start !important;align-content:flex-start !important}.align-content-lg-end{-ms-flex-line-pack:end !important;align-content:flex-end !important}.align-content-lg-center{-ms-flex-line-pack:center !important;align-content:center !important}.align-content-lg-between{-ms-flex-line-pack:justify !important;align-content:space-between !important}.align-content-lg-around{-ms-flex-line-pack:distribute !important;align-content:space-around !important}.align-content-lg-stretch{-ms-flex-line-pack:stretch !important;align-content:stretch !important}.align-self-lg-auto{-ms-flex-item-align:auto !important;align-self:auto !important}.align-self-lg-start{-ms-flex-item-align:start !important;align-self:flex-start !important}.align-self-lg-end{-ms-flex-item-align:end !important;align-self:flex-end !important}.align-self-lg-center{-ms-flex-item-align:center !important;align-self:center !important}.align-self-lg-baseline{-ms-flex-item-align:baseline !important;align-self:baseline !important}.align-self-lg-stretch{-ms-flex-item-align:stretch !important;align-self:stretch !important}}@media (min-width: 1200px){.flex-xl-row{-webkit-box-orient:horizontal !important;-webkit-box-direction:normal !important;-ms-flex-direction:row !important;flex-direction:row !important}.flex-xl-column{-webkit-box-orient:vertical !important;-webkit-box-direction:normal !important;-ms-flex-direction:column !important;flex-direction:column !important}.flex-xl-row-reverse{-webkit-box-orient:horizontal !important;-webkit-box-direction:reverse !important;-ms-flex-direction:row-reverse !important;flex-direction:row-reverse !important}.flex-xl-column-reverse{-webkit-box-orient:vertical !important;-webkit-box-direction:reverse !important;-ms-flex-direction:column-reverse !important;flex-direction:column-reverse !important}.flex-xl-wrap{-ms-flex-wrap:wrap !important;flex-wrap:wrap !important}.flex-xl-nowrap{-ms-flex-wrap:nowrap !important;flex-wrap:nowrap !important}.flex-xl-wrap-reverse{-ms-flex-wrap:wrap-reverse !important;flex-wrap:wrap-reverse !important}.flex-xl-fill{-webkit-box-flex:1 !important;-ms-flex:1 1 auto !important;flex:1 1 auto !important}.flex-xl-grow-0{-webkit-box-flex:0 !important;-ms-flex-positive:0 !important;flex-grow:0 !important}.flex-xl-grow-1{-webkit-box-flex:1 !important;-ms-flex-positive:1 !important;flex-grow:1 !important}.flex-xl-shrink-0{-ms-flex-negative:0 !important;flex-shrink:0 !important}.flex-xl-shrink-1{-ms-flex-negative:1 !important;flex-shrink:1 !important}.justify-content-xl-start{-webkit-box-pack:start !important;-ms-flex-pack:start !important;justify-content:flex-start !important}.justify-content-xl-end{-webkit-box-pack:end !important;-ms-flex-pack:end !important;justify-content:flex-end !important}.justify-content-xl-center{-webkit-box-pack:center !important;-ms-flex-pack:center !important;justify-content:center !important}.justify-content-xl-between{-webkit-box-pack:justify !important;-ms-flex-pack:justify !important;justify-content:space-between !important}.justify-content-xl-around{-ms-flex-pack:distribute !important;justify-content:space-around !important}.align-items-xl-start{-webkit-box-align:start !important;-ms-flex-align:start !important;align-items:flex-start !important}.align-items-xl-end{-webkit-box-align:end !important;-ms-flex-align:end !important;align-items:flex-end !important}.align-items-xl-center{-webkit-box-align:center !important;-ms-flex-align:center !important;align-items:center !important}.align-items-xl-baseline{-webkit-box-align:baseline !important;-ms-flex-align:baseline !important;align-items:baseline !important}.align-items-xl-stretch{-webkit-box-align:stretch !important;-ms-flex-align:stretch !important;align-items:stretch !important}.align-content-xl-start{-ms-flex-line-pack:start !important;align-content:flex-start !important}.align-content-xl-end{-ms-flex-line-pack:end !important;align-content:flex-end !important}.align-content-xl-center{-ms-flex-line-pack:center !important;align-content:center !important}.align-content-xl-between{-ms-flex-line-pack:justify !important;align-content:space-between !important}.align-content-xl-around{-ms-flex-line-pack:distribute !important;align-content:space-around !important}.align-content-xl-stretch{-ms-flex-line-pack:stretch !important;align-content:stretch !important}.align-self-xl-auto{-ms-flex-item-align:auto !important;align-self:auto !important}.align-self-xl-start{-ms-flex-item-align:start !important;align-self:flex-start !important}.align-self-xl-end{-ms-flex-item-align:end !important;align-self:flex-end !important}.align-self-xl-center{-ms-flex-item-align:center !important;align-self:center !important}.align-self-xl-baseline{-ms-flex-item-align:baseline !important;align-self:baseline !important}.align-self-xl-stretch{-ms-flex-item-align:stretch !important;align-self:stretch !important}}.w-25{width:25% !important}.w-50{width:50% !important}.w-75{width:75% !important}.w-100{width:100% !important}.w-auto{width:auto !important}.h-25{height:25% !important}.h-50{height:50% !important}.h-75{height:75% !important}.h-100{height:100% !important}.h-auto{height:auto !important}.mw-100{max-width:100% !important}.mh-100{max-height:100% !important}.m-0{margin:0 !important}.mt-0,.my-0{margin-top:0 !important}.mr-0,.mx-0{margin-right:0 !important}.mb-0,.my-0{margin-bottom:0 !important}.ml-0,.mx-0{margin-left:0 !important}.m-1{margin:.25rem !important}.mt-1,.my-1{margin-top:.25rem !important}.mr-1,.mx-1{margin-right:.25rem !important}.mb-1,.my-1{margin-bottom:.25rem !important}.ml-1,.mx-1{margin-left:.25rem !important}.m-2{margin:.5rem !important}.mt-2,.my-2{margin-top:.5rem !important}.mr-2,.mx-2{margin-right:.5rem !important}.mb-2,.my-2{margin-bottom:.5rem !important}.ml-2,.mx-2{margin-left:.5rem !important}.m-3{margin:1rem !important}.mt-3,.my-3{margin-top:1rem !important}.mr-3,.mx-3{margin-right:1rem !important}.mb-3,.my-3{margin-bottom:1rem !important}.ml-3,.mx-3{margin-left:1rem !important}.m-4{margin:1.5rem !important}.mt-4,.my-4{margin-top:1.5rem !important}.mr-4,.mx-4{margin-right:1.5rem !important}.mb-4,.my-4{margin-bottom:1.5rem !important}.ml-4,.mx-4{margin-left:1.5rem !important}.m-5{margin:3rem !important}.mt-5,.my-5{margin-top:3rem !important}.mr-5,.mx-5{margin-right:3rem !important}.mb-5,.my-5{margin-bottom:3rem !important}.ml-5,.mx-5{margin-left:3rem !important}.p-0{padding:0 !important}.pt-0,.py-0{padding-top:0 !important}.pr-0,.px-0{padding-right:0 !important}.pb-0,.py-0{padding-bottom:0 !important}.pl-0,.px-0{padding-left:0 !important}.p-1{padding:.25rem !important}.pt-1,.py-1{padding-top:.25rem !important}.pr-1,.px-1{padding-right:.25rem !important}.pb-1,.py-1{padding-bottom:.25rem !important}.pl-1,.px-1{padding-left:.25rem !important}.p-2{padding:.5rem !important}.pt-2,.py-2{padding-top:.5rem !important}.pr-2,.px-2{padding-right:.5rem !important}.pb-2,.py-2{padding-bottom:.5rem !important}.pl-2,.px-2{padding-left:.5rem !important}.p-3{padding:1rem !important}.pt-3,.py-3{padding-top:1rem !important}.pr-3,.px-3{padding-right:1rem !important}.pb-3,.py-3{padding-bottom:1rem !important}.pl-3,.px-3{padding-left:1rem !important}.p-4{padding:1.5rem !important}.pt-4,.py-4{padding-top:1.5rem !important}.pr-4,.px-4{padding-right:1.5rem !important}.pb-4,.py-4{padding-bottom:1.5rem !important}.pl-4,.px-4{padding-left:1.5rem !important}.p-5{padding:3rem !important}.pt-5,.py-5{padding-top:3rem !important}.pr-5,.px-5{padding-right:3rem !important}.pb-5,.py-5{padding-bottom:3rem !important}.pl-5,.px-5{padding-left:3rem !important}.m-auto{margin:auto !important}.mt-auto,.my-auto{margin-top:auto !important}.mr-auto,.mx-auto{margin-right:auto !important}.mb-auto,.my-auto{margin-bottom:auto !important}.ml-auto,.mx-auto{margin-left:auto !important}@media (min-width: 576px){.m-sm-0{margin:0 !important}.mt-sm-0,.my-sm-0{margin-top:0 !important}.mr-sm-0,.mx-sm-0{margin-right:0 !important}.mb-sm-0,.my-sm-0{margin-bottom:0 !important}.ml-sm-0,.mx-sm-0{margin-left:0 !important}.m-sm-1{margin:.25rem !important}.mt-sm-1,.my-sm-1{margin-top:.25rem !important}.mr-sm-1,.mx-sm-1{margin-right:.25rem !important}.mb-sm-1,.my-sm-1{margin-bottom:.25rem !important}.ml-sm-1,.mx-sm-1{margin-left:.25rem !important}.m-sm-2{margin:.5rem !important}.mt-sm-2,.my-sm-2{margin-top:.5rem !important}.mr-sm-2,.mx-sm-2{margin-right:.5rem !important}.mb-sm-2,.my-sm-2{margin-bottom:.5rem !important}.ml-sm-2,.mx-sm-2{margin-left:.5rem !important}.m-sm-3{margin:1rem !important}.mt-sm-3,.my-sm-3{margin-top:1rem !important}.mr-sm-3,.mx-sm-3{margin-right:1rem !important}.mb-sm-3,.my-sm-3{margin-bottom:1rem !important}.ml-sm-3,.mx-sm-3{margin-left:1rem !important}.m-sm-4{margin:1.5rem !important}.mt-sm-4,.my-sm-4{margin-top:1.5rem !important}.mr-sm-4,.mx-sm-4{margin-right:1.5rem !important}.mb-sm-4,.my-sm-4{margin-bottom:1.5rem !important}.ml-sm-4,.mx-sm-4{margin-left:1.5rem !important}.m-sm-5{margin:3rem !important}.mt-sm-5,.my-sm-5{margin-top:3rem !important}.mr-sm-5,.mx-sm-5{margin-right:3rem !important}.mb-sm-5,.my-sm-5{margin-bottom:3rem !important}.ml-sm-5,.mx-sm-5{margin-left:3rem !important}.p-sm-0{padding:0 !important}.pt-sm-0,.py-sm-0{padding-top:0 !important}.pr-sm-0,.px-sm-0{padding-right:0 !important}.pb-sm-0,.py-sm-0{padding-bottom:0 !important}.pl-sm-0,.px-sm-0{padding-left:0 !important}.p-sm-1{padding:.25rem !important}.pt-sm-1,.py-sm-1{padding-top:.25rem !important}.pr-sm-1,.px-sm-1{padding-right:.25rem !important}.pb-sm-1,.py-sm-1{padding-bottom:.25rem !important}.pl-sm-1,.px-sm-1{padding-left:.25rem !important}.p-sm-2{padding:.5rem !important}.pt-sm-2,.py-sm-2{padding-top:.5rem !important}.pr-sm-2,.px-sm-2{padding-right:.5rem !important}.pb-sm-2,.py-sm-2{padding-bottom:.5rem !important}.pl-sm-2,.px-sm-2{padding-left:.5rem !important}.p-sm-3{padding:1rem !important}.pt-sm-3,.py-sm-3{padding-top:1rem !important}.pr-sm-3,.px-sm-3{padding-right:1rem !important}.pb-sm-3,.py-sm-3{padding-bottom:1rem !important}.pl-sm-3,.px-sm-3{padding-left:1rem !important}.p-sm-4{padding:1.5rem !important}.pt-sm-4,.py-sm-4{padding-top:1.5rem !important}.pr-sm-4,.px-sm-4{padding-right:1.5rem !important}.pb-sm-4,.py-sm-4{padding-bottom:1.5rem !important}.pl-sm-4,.px-sm-4{padding-left:1.5rem !important}.p-sm-5{padding:3rem !important}.pt-sm-5,.py-sm-5{padding-top:3rem !important}.pr-sm-5,.px-sm-5{padding-right:3rem !important}.pb-sm-5,.py-sm-5{padding-bottom:3rem !important}.pl-sm-5,.px-sm-5{padding-left:3rem !important}.m-sm-auto{margin:auto !important}.mt-sm-auto,.my-sm-auto{margin-top:auto !important}.mr-sm-auto,.mx-sm-auto{margin-right:auto !important}.mb-sm-auto,.my-sm-auto{margin-bottom:auto !important}.ml-sm-auto,.mx-sm-auto{margin-left:auto !important}}@media (min-width: 768px){.m-md-0{margin:0 !important}.mt-md-0,.my-md-0{margin-top:0 !important}.mr-md-0,.mx-md-0{margin-right:0 !important}.mb-md-0,.my-md-0{margin-bottom:0 !important}.ml-md-0,.mx-md-0{margin-left:0 !important}.m-md-1{margin:.25rem !important}.mt-md-1,.my-md-1{margin-top:.25rem !important}.mr-md-1,.mx-md-1{margin-right:.25rem !important}.mb-md-1,.my-md-1{margin-bottom:.25rem !important}.ml-md-1,.mx-md-1{margin-left:.25rem !important}.m-md-2{margin:.5rem !important}.mt-md-2,.my-md-2{margin-top:.5rem !important}.mr-md-2,.mx-md-2{margin-right:.5rem !important}.mb-md-2,.my-md-2{margin-bottom:.5rem !important}.ml-md-2,.mx-md-2{margin-left:.5rem !important}.m-md-3{margin:1rem !important}.mt-md-3,.my-md-3{margin-top:1rem !important}.mr-md-3,.mx-md-3{margin-right:1rem !important}.mb-md-3,.my-md-3{margin-bottom:1rem !important}.ml-md-3,.mx-md-3{margin-left:1rem !important}.m-md-4{margin:1.5rem !important}.mt-md-4,.my-md-4{margin-top:1.5rem !important}.mr-md-4,.mx-md-4{margin-right:1.5rem !important}.mb-md-4,.my-md-4{margin-bottom:1.5rem !important}.ml-md-4,.mx-md-4{margin-left:1.5rem !important}.m-md-5{margin:3rem !important}.mt-md-5,.my-md-5{margin-top:3rem !important}.mr-md-5,.mx-md-5{margin-right:3rem !important}.mb-md-5,.my-md-5{margin-bottom:3rem !important}.ml-md-5,.mx-md-5{margin-left:3rem !important}.p-md-0{padding:0 !important}.pt-md-0,.py-md-0{padding-top:0 !important}.pr-md-0,.px-md-0{padding-right:0 !important}.pb-md-0,.py-md-0{padding-bottom:0 !important}.pl-md-0,.px-md-0{padding-left:0 !important}.p-md-1{padding:.25rem !important}.pt-md-1,.py-md-1{padding-top:.25rem !important}.pr-md-1,.px-md-1{padding-right:.25rem !important}.pb-md-1,.py-md-1{padding-bottom:.25rem !important}.pl-md-1,.px-md-1{padding-left:.25rem !important}.p-md-2{padding:.5rem !important}.pt-md-2,.py-md-2{padding-top:.5rem !important}.pr-md-2,.px-md-2{padding-right:.5rem !important}.pb-md-2,.py-md-2{padding-bottom:.5rem !important}.pl-md-2,.px-md-2{padding-left:.5rem !important}.p-md-3{padding:1rem !important}.pt-md-3,.py-md-3{padding-top:1rem !important}.pr-md-3,.px-md-3{padding-right:1rem !important}.pb-md-3,.py-md-3{padding-bottom:1rem !important}.pl-md-3,.px-md-3{padding-left:1rem !important}.p-md-4{padding:1.5rem !important}.pt-md-4,.py-md-4{padding-top:1.5rem !important}.pr-md-4,.px-md-4{padding-right:1.5rem !important}.pb-md-4,.py-md-4{padding-bottom:1.5rem !important}.pl-md-4,.px-md-4{padding-left:1.5rem !important}.p-md-5{padding:3rem !important}.pt-md-5,.py-md-5{padding-top:3rem !important}.pr-md-5,.px-md-5{padding-right:3rem !important}.pb-md-5,.py-md-5{padding-bottom:3rem !important}.pl-md-5,.px-md-5{padding-left:3rem !important}.m-md-auto{margin:auto !important}.mt-md-auto,.my-md-auto{margin-top:auto !important}.mr-md-auto,.mx-md-auto{margin-right:auto !important}.mb-md-auto,.my-md-auto{margin-bottom:auto !important}.ml-md-auto,.mx-md-auto{margin-left:auto !important}}@media (min-width: 992px){.m-lg-0{margin:0 !important}.mt-lg-0,.my-lg-0{margin-top:0 !important}.mr-lg-0,.mx-lg-0{margin-right:0 !important}.mb-lg-0,.my-lg-0{margin-bottom:0 !important}.ml-lg-0,.mx-lg-0{margin-left:0 !important}.m-lg-1{margin:.25rem !important}.mt-lg-1,.my-lg-1{margin-top:.25rem !important}.mr-lg-1,.mx-lg-1{margin-right:.25rem !important}.mb-lg-1,.my-lg-1{margin-bottom:.25rem !important}.ml-lg-1,.mx-lg-1{margin-left:.25rem !important}.m-lg-2{margin:.5rem !important}.mt-lg-2,.my-lg-2{margin-top:.5rem !important}.mr-lg-2,.mx-lg-2{margin-right:.5rem !important}.mb-lg-2,.my-lg-2{margin-bottom:.5rem !important}.ml-lg-2,.mx-lg-2{margin-left:.5rem !important}.m-lg-3{margin:1rem !important}.mt-lg-3,.my-lg-3{margin-top:1rem !important}.mr-lg-3,.mx-lg-3{margin-right:1rem !important}.mb-lg-3,.my-lg-3{margin-bottom:1rem !important}.ml-lg-3,.mx-lg-3{margin-left:1rem !important}.m-lg-4{margin:1.5rem !important}.mt-lg-4,.my-lg-4{margin-top:1.5rem !important}.mr-lg-4,.mx-lg-4{margin-right:1.5rem !important}.mb-lg-4,.my-lg-4{margin-bottom:1.5rem !important}.ml-lg-4,.mx-lg-4{margin-left:1.5rem !important}.m-lg-5{margin:3rem !important}.mt-lg-5,.my-lg-5{margin-top:3rem !important}.mr-lg-5,.mx-lg-5{margin-right:3rem !important}.mb-lg-5,.my-lg-5{margin-bottom:3rem !important}.ml-lg-5,.mx-lg-5{margin-left:3rem !important}.p-lg-0{padding:0 !important}.pt-lg-0,.py-lg-0{padding-top:0 !important}.pr-lg-0,.px-lg-0{padding-right:0 !important}.pb-lg-0,.py-lg-0{padding-bottom:0 !important}.pl-lg-0,.px-lg-0{padding-left:0 !important}.p-lg-1{padding:.25rem !important}.pt-lg-1,.py-lg-1{padding-top:.25rem !important}.pr-lg-1,.px-lg-1{padding-right:.25rem !important}.pb-lg-1,.py-lg-1{padding-bottom:.25rem !important}.pl-lg-1,.px-lg-1{padding-left:.25rem !important}.p-lg-2{padding:.5rem !important}.pt-lg-2,.py-lg-2{padding-top:.5rem !important}.pr-lg-2,.px-lg-2{padding-right:.5rem !important}.pb-lg-2,.py-lg-2{padding-bottom:.5rem !important}.pl-lg-2,.px-lg-2{padding-left:.5rem !important}.p-lg-3{padding:1rem !important}.pt-lg-3,.py-lg-3{padding-top:1rem !important}.pr-lg-3,.px-lg-3{padding-right:1rem !important}.pb-lg-3,.py-lg-3{padding-bottom:1rem !important}.pl-lg-3,.px-lg-3{padding-left:1rem !important}.p-lg-4{padding:1.5rem !important}.pt-lg-4,.py-lg-4{padding-top:1.5rem !important}.pr-lg-4,.px-lg-4{padding-right:1.5rem !important}.pb-lg-4,.py-lg-4{padding-bottom:1.5rem !important}.pl-lg-4,.px-lg-4{padding-left:1.5rem !important}.p-lg-5{padding:3rem !important}.pt-lg-5,.py-lg-5{padding-top:3rem !important}.pr-lg-5,.px-lg-5{padding-right:3rem !important}.pb-lg-5,.py-lg-5{padding-bottom:3rem !important}.pl-lg-5,.px-lg-5{padding-left:3rem !important}.m-lg-auto{margin:auto !important}.mt-lg-auto,.my-lg-auto{margin-top:auto !important}.mr-lg-auto,.mx-lg-auto{margin-right:auto !important}.mb-lg-auto,.my-lg-auto{margin-bottom:auto !important}.ml-lg-auto,.mx-lg-auto{margin-left:auto !important}}@media (min-width: 1200px){.m-xl-0{margin:0 !important}.mt-xl-0,.my-xl-0{margin-top:0 !important}.mr-xl-0,.mx-xl-0{margin-right:0 !important}.mb-xl-0,.my-xl-0{margin-bottom:0 !important}.ml-xl-0,.mx-xl-0{margin-left:0 !important}.m-xl-1{margin:.25rem !important}.mt-xl-1,.my-xl-1{margin-top:.25rem !important}.mr-xl-1,.mx-xl-1{margin-right:.25rem !important}.mb-xl-1,.my-xl-1{margin-bottom:.25rem !important}.ml-xl-1,.mx-xl-1{margin-left:.25rem !important}.m-xl-2{margin:.5rem !important}.mt-xl-2,.my-xl-2{margin-top:.5rem !important}.mr-xl-2,.mx-xl-2{margin-right:.5rem !important}.mb-xl-2,.my-xl-2{margin-bottom:.5rem !important}.ml-xl-2,.mx-xl-2{margin-left:.5rem !important}.m-xl-3{margin:1rem !important}.mt-xl-3,.my-xl-3{margin-top:1rem !important}.mr-xl-3,.mx-xl-3{margin-right:1rem !important}.mb-xl-3,.my-xl-3{margin-bottom:1rem !important}.ml-xl-3,.mx-xl-3{margin-left:1rem !important}.m-xl-4{margin:1.5rem !important}.mt-xl-4,.my-xl-4{margin-top:1.5rem !important}.mr-xl-4,.mx-xl-4{margin-right:1.5rem !important}.mb-xl-4,.my-xl-4{margin-bottom:1.5rem !important}.ml-xl-4,.mx-xl-4{margin-left:1.5rem !important}.m-xl-5{margin:3rem !important}.mt-xl-5,.my-xl-5{margin-top:3rem !important}.mr-xl-5,.mx-xl-5{margin-right:3rem !important}.mb-xl-5,.my-xl-5{margin-bottom:3rem !important}.ml-xl-5,.mx-xl-5{margin-left:3rem !important}.p-xl-0{padding:0 !important}.pt-xl-0,.py-xl-0{padding-top:0 !important}.pr-xl-0,.px-xl-0{padding-right:0 !important}.pb-xl-0,.py-xl-0{padding-bottom:0 !important}.pl-xl-0,.px-xl-0{padding-left:0 !important}.p-xl-1{padding:.25rem !important}.pt-xl-1,.py-xl-1{padding-top:.25rem !important}.pr-xl-1,.px-xl-1{padding-right:.25rem !important}.pb-xl-1,.py-xl-1{padding-bottom:.25rem !important}.pl-xl-1,.px-xl-1{padding-left:.25rem !important}.p-xl-2{padding:.5rem !important}.pt-xl-2,.py-xl-2{padding-top:.5rem !important}.pr-xl-2,.px-xl-2{padding-right:.5rem !important}.pb-xl-2,.py-xl-2{padding-bottom:.5rem !important}.pl-xl-2,.px-xl-2{padding-left:.5rem !important}.p-xl-3{padding:1rem !important}.pt-xl-3,.py-xl-3{padding-top:1rem !important}.pr-xl-3,.px-xl-3{padding-right:1rem !important}.pb-xl-3,.py-xl-3{padding-bottom:1rem !important}.pl-xl-3,.px-xl-3{padding-left:1rem !important}.p-xl-4{padding:1.5rem !important}.pt-xl-4,.py-xl-4{padding-top:1.5rem !important}.pr-xl-4,.px-xl-4{padding-right:1.5rem !important}.pb-xl-4,.py-xl-4{padding-bottom:1.5rem !important}.pl-xl-4,.px-xl-4{padding-left:1.5rem !important}.p-xl-5{padding:3rem !important}.pt-xl-5,.py-xl-5{padding-top:3rem !important}.pr-xl-5,.px-xl-5{padding-right:3rem !important}.pb-xl-5,.py-xl-5{padding-bottom:3rem !important}.pl-xl-5,.px-xl-5{padding-left:3rem !important}.m-xl-auto{margin:auto !important}.mt-xl-auto,.my-xl-auto{margin-top:auto !important}.mr-xl-auto,.mx-xl-auto{margin-right:auto !important}.mb-xl-auto,.my-xl-auto{margin-bottom:auto !important}.ml-xl-auto,.mx-xl-auto{margin-left:auto !important}}.visible{visibility:visible !important}.invisible{visibility:hidden !important}
\ No newline at end of file
diff --git a/css/styles.scss b/css/styles.scss
index bfdaeb278..e9204bc08 100644
--- a/css/styles.scss
+++ b/css/styles.scss
@@ -62,6 +62,9 @@ a:visited {
.text-input {
color: #fff;
background-color: #000;
+ border-style: solid;
+ border-width: 1px;
+ border-color: white;
}
/* Notification icon (for create program right now only) */
@@ -333,3 +336,43 @@ a:visited {
.smallfont {
font-size: $defaultFontSize * 0.8125;
}
+
+.bbcheckbox {
+ position: relative;
+ display: inline;
+ label {
+ width: 20px;
+ height: 20px;
+ cursor: pointer;
+ position: absolute;
+ top: 0;
+ left: 0;
+ background: black;
+ border-width: 1px;
+ border-color: white;
+ border-style: solid;
+ &:after {
+ content: '';
+ width: 9px;
+ height: 5px;
+ position: absolute;
+ top: 4px;
+ left: 4px;
+ border: 3px solid white;
+ border-top: none;
+ border-right: none;
+ opacity: 0;
+ transform: rotate(-45deg);
+ }
+ }
+ input[type=checkbox] {
+ visibility: hidden;
+ &:checked + label:after {
+ opacity: 1;
+ }
+ }
+}
+
+
+
+
diff --git a/src/Bladeburner.js b/src/Bladeburner.js
index dbf7677e3..8e0c6d339 100644
--- a/src/Bladeburner.js
+++ b/src/Bladeburner.js
@@ -31,6 +31,8 @@ import { getTimestamp } from "../utils/helpers/getTi
import { removeElement } from "../utils/uiHelpers/removeElement";
import { removeElementById } from "../utils/uiHelpers/removeElementById";
+const stealthIcon = ` `
+const killIcon = ``
const CityNames = ["Aevum", "Chongqing", "Sector-12", "New Tokyo", "Ishima", "Volhaven"];
@@ -1799,6 +1801,12 @@ Bladeburner.prototype.createContent = function() {
DomElems.bladeburnerDiv.appendChild(DomElems.overviewConsoleParentDiv);
DomElems.bladeburnerDiv.appendChild(DomElems.actionAndSkillsDiv);
+
+ // legend
+ const legend = createElement("div")
+ legend.innerHTML = `${stealthIcon}= This action requires stealth, ${killIcon} = This action involves retirement`
+ DomElems.bladeburnerDiv.appendChild(legend);
+
document.getElementById("entire-game-container").appendChild(DomElems.bladeburnerDiv);
if (this.consoleLogs.length === 0) {
@@ -2166,12 +2174,12 @@ Bladeburner.prototype.createBlackOpsContent = function() {
return (a.reqdRank - b.reqdRank);
});
- for (var i = 0; i < blackops.length; ++i) {
+ for (var i = blackops.length-1; i >= 0 ; --i) {
+ if (this.blackops[[blackops[i].name]] == null && i !== 0 && this.blackops[[blackops[i-1].name]] == null) {continue;} // If this one nor the next are completed then this isn't unlocked yet.
DomElems.blackops[blackops[i].name] = createElement("div", {
class:"bladeburner-action", name:blackops[i].name
});
DomElems.actionsAndSkillsList.appendChild(DomElems.blackops[blackops[i].name]);
- if (this.blackops[[blackops[i].name]] == null) {break;} //Can't be found in completed blackops
}
}
@@ -2504,7 +2512,8 @@ Bladeburner.prototype.updateContractsUIElement = function(el, action) {
el.appendChild(createElement("pre", { //Info
display:"inline-block",
innerHTML:action.desc + "\n\n" +
- "Estimated success chance: " + formatNumber(estimatedSuccessChance*100, 1) + "%\n" +
+ `Estimated success chance: ${formatNumber(estimatedSuccessChance*100, 1)}% ${action.isStealth?stealthIcon:''}${action.isKill?killIcon:''}\n` +
+
"Time Required (s): " + formatNumber(actionTime, 0) + "\n" +
"Contracts remaining: " + Math.floor(action.count) + "\n" +
"Successes: " + action.successes + "\n" +
@@ -2518,14 +2527,21 @@ Bladeburner.prototype.updateContractsUIElement = function(el, action) {
for:autolevelCheckboxId, innerText:"Autolevel",color:"white",
tooltip:"Automatically increase contract level when possible"
}));
- var autolevelCheckbox = createElement("input", {
- type:"checkbox", id:autolevelCheckboxId, margin:"4px",
- checked:action.autoLevel,
- changeListener:()=>{
- action.autoLevel = autolevelCheckbox.checked;
- }
+
+ const checkboxDiv = createElement("div", { class: "bbcheckbox" });
+ const checkboxInput = createElement("input", {
+ type:"checkbox",
+ id: autolevelCheckboxId,
+ checked: action.autoLevel,
+ changeListener: () => {
+ action.autoLevel = checkboxInput.checked;
+ },
});
- el.appendChild(autolevelCheckbox);
+ const checkmarkLabel = createElement("label", { for: autolevelCheckboxId });
+ checkboxDiv.appendChild(checkboxInput);
+ checkboxDiv.appendChild(checkmarkLabel);
+
+ el.appendChild(checkboxDiv);
}
Bladeburner.prototype.updateOperationsUIElement = function(el, action) {
@@ -2640,7 +2656,7 @@ Bladeburner.prototype.updateOperationsUIElement = function(el, action) {
el.appendChild(createElement("pre", {
display:"inline-block",
innerHTML:action.desc + "\n\n" +
- "Estimated success chance: " + formatNumber(estimatedSuccessChance*100, 1) + "%\n" +
+ `Estimated success chance: ${formatNumber(estimatedSuccessChance*100, 1)}% ${action.isStealth?stealthIcon:''}${action.isKill?killIcon:''}\n` +
"Time Required(s): " + formatNumber(actionTime, 0) + "\n" +
"Operations remaining: " + Math.floor(action.count) + "\n" +
"Successes: " + action.successes + "\n" +
@@ -2654,14 +2670,21 @@ Bladeburner.prototype.updateOperationsUIElement = function(el, action) {
for:autolevelCheckboxId, innerText:"Autolevel",color:"white",
tooltip:"Automatically increase operation level when possible"
}));
- var autolevelCheckbox = createElement("input", {
- type:"checkbox", id:autolevelCheckboxId, margin:"4px",
- checked:action.autoLevel,
- changeListener:()=>{
- action.autoLevel = autolevelCheckbox.checked;
- }
+
+ const checkboxDiv = createElement("div", { class: "bbcheckbox" });
+ const checkboxInput = createElement("input", {
+ type:"checkbox",
+ id: autolevelCheckboxId,
+ checked: action.autoLevel,
+ changeListener: () => {
+ action.autoLevel = checkboxInput.checked;
+ },
});
- el.appendChild(autolevelCheckbox);
+ const checkmarkLabel = createElement("label", { for: autolevelCheckboxId });
+ checkboxDiv.appendChild(checkboxInput);
+ checkboxDiv.appendChild(checkmarkLabel);
+
+ el.appendChild(checkboxDiv);
}
Bladeburner.prototype.updateBlackOpsUIElement = function(el, action) {
@@ -2760,7 +2783,7 @@ Bladeburner.prototype.updateBlackOpsUIElement = function(el, action) {
}));
el.appendChild(createElement("p", {
display:"inline-block",
- innerHTML:"Estimated Success Chance: " + formatNumber(estimatedSuccessChance*100, 1) + "%\n" +
+ innerHTML:`Estimated Success Chance: ${formatNumber(estimatedSuccessChance*100, 1)}% ${action.isStealth?stealthIcon:''}${action.isKill?killIcon:''}\n` +
"Time Required(s): " + formatNumber(actionTime, 0),
}))
}
diff --git a/src/DevMenu.js b/src/DevMenu.js
deleted file mode 100644
index 48a4cbee1..000000000
--- a/src/DevMenu.js
+++ /dev/null
@@ -1,740 +0,0 @@
-import { AugmentationNames } from "./Augmentation/data/AugmentationNames";
-import { CodingContractTypes } from "./CodingContracts";
-import { generateContract,
- generateRandomContract,
- generateRandomContractOnHome } from "./CodingContractGenerator";
-import { Companies } from "./Company/Companies";
-import { Company } from "./Company/Company";
-import { Programs } from "./Programs/Programs";
-import { Factions } from "./Faction/Factions";
-import { Player } from "./Player";
-import { AllServers } from "./Server/AllServers";
-import { hackWorldDaemon } from "./RedPill";
-import { StockMarket,
- SymbolToStockMap } from "./StockMarket/StockMarket";
-import { Stock } from "./StockMarket/Stock";
-import { Terminal } from "./Terminal";
-
-import { numeralWrapper } from "./ui/numeralFormat";
-
-import { dialogBoxCreate } from "../utils/DialogBox";
-import { exceptionAlert } from "../utils/helpers/exceptionAlert";
-import { createElement } from "../utils/uiHelpers/createElement";
-import { createOptionElement } from "../utils/uiHelpers/createOptionElement";
-import { getSelectText } from "../utils/uiHelpers/getSelectData";
-import { removeElementById } from "../utils/uiHelpers/removeElementById";
-
-const devMenuContainerId = "dev-menu-container";
-
-export function createDevMenu() {
- if (process.env.NODE_ENV !== "development") {
- throw new Error("Cannot create Dev Menu because you are not in a dev build");
- }
-
- const devMenuText = createElement("h1", {
- display: "block",
- innerText: "Development Menu - Only meant to be used for testing/debugging",
- });
-
- // Generic
- const genericHeader = createElement("h2", {
- display: "block",
- innerText: "Generic"
- });
-
- const addMoney = createElement("button", {
- class: "std-button",
- clickListener: () => {
- Player.gainMoney(1e15);
- },
- display: "block",
- innerText: "Add $1000t",
- });
-
- const addMoney2 = createElement("button", {
- class: "std-button",
- clickListener: () => {
- Player.gainMoney(1e12);
- },
- display: "block",
- innerText: "Add $1t",
- })
-
- const addRam = createElement("button", {
- class: "std-button",
- clickListener: () => {
- Player.getHomeComputer().maxRam *= 2;
- },
- display: "block",
- innerText: "Double Home Computer RAM",
- });
-
- const triggerBitflume = createElement("button", {
- class: "std-button",
- clickListener: () => {
- hackWorldDaemon(Player.bitNodeN, true);
- },
- innerText: "Trigger BitFlume",
- });
-
- const destroyCurrentBitnode = createElement("button", {
- class: "std-button",
- clickListener: () => {
- hackWorldDaemon(Player.bitNodeN);
- },
- innerText: "Destroy Current BitNode",
- tooltip: "Will grant Source-File for the BitNode",
- });
-
- // Experience / stats
- const statsHeader = createElement("h2", {
- display: "block",
- innerText: "Experience/Stats"
- });
-
- const statsHackingExpInput = createElement("input", {
- class: "text-input",
- margin: "5px",
- placeholder: "+/- hacking exp",
- type: "number",
- });
- const statsHackingExpButton = createElement("button", {
- class: "std-button",
- clickListener: () => {
- const exp = parseInt(statsHackingExpInput.value);
- Player.gainHackingExp(exp);
- Player.updateSkillLevels();
- },
- innerText: "Add Hacking Exp",
- });
-
- const statsStrengthExpInput = createElement("input", {
- class: "text-input",
- margin: "5px",
- placeholder: "+/- strength exp",
- type: "number",
- });
- const statsStrengthExpButton = createElement("button", {
- class: "std-button",
- clickListener: () => {
- const exp = parseInt(statsStrengthExpInput.value);
- Player.gainStrengthExp(exp);
- Player.updateSkillLevels();
- },
- innerText: "Add Strength Exp",
- });
-
- const statsDefenseExpInput = createElement("input", {
- class: "text-input",
- margin: "5px",
- placeholder: "+/- defense exp",
- type: "number",
- });
- const statsDefenseExpButton = createElement("button", {
- class: "std-button",
- clickListener: () => {
- const exp = parseInt(statsDefenseExpInput.value);
- Player.gainDefenseExp(exp);
- Player.updateSkillLevels();
- },
- innerText: "Add Defense Exp",
- });
-
- const statsDexterityExpInput = createElement("input", {
- class: "text-input",
- margin: "5px",
- placeholder: "+/- dexterity exp",
- type: "number",
- });
- const statsDexterityExpButton = createElement("button", {
- class: "std-button",
- clickListener: () => {
- const exp = parseInt(statsDexterityExpInput.value);
- Player.gainDexterityExp(exp);
- Player.updateSkillLevels();
- },
- innerText: "Add Dexterity Exp",
- });
-
- const statsAgilityExpInput = createElement("input", {
- class: "text-input",
- margin: "5px",
- placeholder: "+/- agility exp",
- type: "number",
- });
- const statsAgilityExpButton = createElement("button", {
- class: "std-button",
- clickListener: () => {
- const exp = parseInt(statsAgilityExpInput.value);
- Player.gainAgilityExp(exp);
- Player.updateSkillLevels();
- },
- innerText: "Add Agility Exp",
- });
-
- const statsCharismaExpInput = createElement("input", {
- class: "text-input",
- margin: "5px",
- placeholder: "+/- charisma exp",
- type: "number",
- });
- const statsCharismaExpButton = createElement("button", {
- class: "std-button",
- clickListener: () => {
- const exp = parseInt(statsCharismaExpInput.value);
- Player.gainCharismaExp(exp);
- Player.updateSkillLevels();
- },
- innerText: "Add Charisma Exp",
- });
-
- const statsIntelligenceExpInput = createElement("input", {
- class: "text-input",
- margin: "5px",
- placeholder: "+/- intelligence exp",
- type: "number",
- });
- const statsIntelligenceExpButton = createElement("button", {
- class: "std-button",
- clickListener: () => {
- const exp = parseInt(statsIntelligenceExpInput.value);
- Player.gainIntelligenceExp(exp);
- Player.updateSkillLevels();
- },
- innerText: "Add Intelligence Exp",
- });
-
- const statsEnableIntelligenceButton = createElement("button", {
- class: "std-button",
- clickListener: () => {
- Player.intelligence = 1;
- },
- innerText: "Enable Intelligence"
- });
-
- const statsDisableIntelligenceButton = createElement("button", {
- class: "std-button",
- clickListener: () => {
- Player.intelligence = 0;
- },
- innerText: "Disable Intelligence"
- });
-
- // Factions
- const factionsHeader = createElement("h2", {innerText: "Factions"});
-
- const factionsDropdown = createElement("select", {
- class: "dropdown",
- margin: "5px",
- });
- for (const i in Factions) {
- factionsDropdown.options[factionsDropdown.options.length] = new Option(Factions[i].name, Factions[i].name);
- }
-
- const factionsAddButton = createElement("button", {
- class: "std-button",
- clickListener: () => {
- const facName = factionsDropdown.options[factionsDropdown.selectedIndex].value;
- Player.receiveInvite(facName);
- },
- innerText: "Receive Invite to Faction",
- });
-
- const factionsReputationInput = createElement("input", {
- placeholder: "Rep to add to faction",
- type: "number",
- });
-
- const factionsReputationButton = createElement("button", {
- class: "std-button",
- innerText: "Add rep to faction",
- clickListener: () => {
- const facName = getSelectText(factionsDropdown);
- const fac = Factions[facName];
- const rep = parseFloat(factionsReputationInput.value);
- if (fac != null && !isNaN(rep)) {
- fac.playerReputation += rep;
- }
- },
- });
-
- // Augmentations
- const augmentationsHeader = createElement("h2", {innerText: "Augmentations"});
-
- const augmentationsDropdown = createElement("select", {
- class: "dropdown",
- margin: "5px",
- });
- for (const i in AugmentationNames) {
- const augName = AugmentationNames[i];
- augmentationsDropdown.options[augmentationsDropdown.options.length] = new Option(augName, augName);
- }
-
- const augmentationsQueueButton = createElement("button", {
- class: "std-button",
- clickListener: () => {
- Player.queueAugmentation(augmentationsDropdown.options[augmentationsDropdown.selectedIndex].value);
- },
- innerText: "Queue Augmentation",
- });
-
- const giveAllAugmentationsButton = createElement("button", {
- class: "std-button",
- clickListener: () => {
- for (const i in AugmentationNames) {
- const augName = AugmentationNames[i];
- Player.queueAugmentation(augName);
- }
- },
- display: "block",
- innerText: "Queue All Augmentations",
- });
-
- // Source Files
- const sourceFilesHeader = createElement("h2", { innerText: "Source-Files" });
-
- const removeSourceFileDropdown = createElement("select", {
- class: "dropdown",
- margin: "5px",
- });
- for (let i = 0; i < 24; ++i) {
- removeSourceFileDropdown.add(createOptionElement(String(i)));
- }
-
- const removeSourceFileButton = createElement("button", {
- class: "std-button",
- clickListener: () => {
- const numToRemove = parseInt(getSelectText(removeSourceFileDropdown));
- for (let i = 0; i < Player.sourceFiles.length; ++i) {
- if (Player.sourceFiles[i].n === numToRemove) {
- Player.sourceFiles.splice(i, 1);
- hackWorldDaemon(Player.bitNodeN, true);
- return;
- }
- }
- },
- innerText: "Remove Source File and Trigger Bitflume",
- });
-
- // Programs
- const programsHeader = createElement("h2", {innerText: "Programs"});
-
- const programsAddDropdown = createElement("select", {
- class: "dropdown",
- margin: "5px",
- });
- for (const i in Programs) {
- const progName = Programs[i].name;
- programsAddDropdown.options[programsAddDropdown.options.length] = new Option(progName, progName);
- }
-
- const programsAddButton = createElement("button", {
- class: "std-button",
- clickListener: () => {
- const program = programsAddDropdown.options[programsAddDropdown.selectedIndex].value;
- if(!Player.hasProgram(program)) {
- Player.getHomeComputer().programs.push(program);
- }
- },
- innerText: "Add Program",
- })
-
- // Servers
- const serversHeader = createElement("h2", {innerText: "Servers"});
-
- const serversOpenAll = createElement("button", {
- class: "std-button",
- clickListener: () => {
- for (const i in AllServers) {
- AllServers[i].hasAdminRights = true;
- AllServers[i].sshPortOpen = true;
- AllServers[i].ftpPortOpen = true;
- AllServers[i].smtpPortOpen = true;
- AllServers[i].httpPortOpen = true;
- AllServers[i].sqlPortOpen = true;
- AllServers[i].openPortCount = 5;
- }
- },
- display: "block",
- innerText: "Get Admin Rights to all servers",
- });
-
- const serversMinSecurityAll = createElement("button", {
- class: "std-button",
- clickListener: () => {
- for (const i in AllServers) {
- AllServers[i].hackDifficulty = AllServers[i].minDifficulty;
- }
- },
- display: "block",
- innerText: "Set all servers to min security",
- });
-
- const serversMaxMoneyAll = createElement("button", {
- class: "std-button",
- clickListener: () => {
- for (const i in AllServers) {
- AllServers[i].moneyAvailable = AllServers[i].moneyMax;
- }
- },
- display: "block",
- innerText: "Set all servers to max money",
- });
-
- const serversConnectToDropdown = createElement("select", {class: "dropdown"});
- for (const i in AllServers) {
- const hn = AllServers[i].hostname;
- serversConnectToDropdown.options[serversConnectToDropdown.options.length] = new Option(hn, hn);
- }
-
- const serversConnectToButton = createElement("button", {
- class: "std-button",
- clickListener: () => {
- const host = serversConnectToDropdown.options[serversConnectToDropdown.selectedIndex].value;
- Terminal.connectToServer(host);
- },
- innerText: "Connect to server",
- });
-
- // Companies
- const companiesHeader = createElement("h2", { innerText: "Companies" });
-
- const companiesDropdown = createElement("select", {
- class: "dropdown",
- margin: "5px",
- });
- for (const c in Companies) {
- companiesDropdown.add(createOptionElement(Companies[c].name));
- }
-
- const companyReputationInput = createElement("input", {
- margin: "5px",
- placeholder: "Rep to add to company",
- type: "number",
- });
-
- const companyReputationButton = createElement("button", {
- class: "std-button",
- innerText: "Add rep to company",
- clickListener: () => {
- const compName = getSelectText(companiesDropdown);
- const company = Companies[compName];
- const rep = parseFloat(companyReputationInput.value);
- if (company != null && !isNaN(rep)) {
- company.playerReputation += rep;
- } else {
- console.warn(`Invalid input for Dev Menu Company Rep. Company Name: ${compName}. Rep: ${rep}`);
- }
- }
- });
-
- // Bladeburner
- const bladeburnerHeader = createElement("h2", {innerText: "Bladeburner"});
-
- const bladeburnerGainRankInput = createElement("input", {
- class: "text-input",
- margin: "5px",
- placeholder: "Rank to gain (or negative to lose rank)",
- type: "number",
- });
-
- const bladeburnerGainRankButton = createElement("button", {
- class: "std-button",
- clickListener: () => {
- try {
- const rank = parseInt(bladeburnerGainRankInput.value);
- Player.bladeburner.changeRank(rank);
- } catch(e) {
- exceptionAlert(`Failed to change Bladeburner Rank in dev menu: ${e}`);
- }
- },
- innerText: "Gain Bladeburner Rank",
- });
-
- const bladeburnerStoredCyclesInput = createElement("input", {
- class: "text-input",
- margin: "5px",
- placeholder: "# Cycles to Add",
- type: "number",
- });
-
- const bladeburnerStoredCyclesButton = createElement("button", {
- class: "std-button",
- clickListener: () => {
- try {
- const cycles = parseInt(bladeburnerStoredCyclesInput.value);
- Player.bladeburner.storedCycles += cycles;
- } catch(e) {
- exceptionAlert(`Failed to add cycles to Bladeburner in dev menu: ${e}`);
- }
- },
- innerText: "Add Cycles to Bladeburner mechanic",
- });
-
- // Gang
- const gangHeader = createElement("h2", {innerText: "Gang"});
-
- const gangStoredCyclesInput = createElement("input", {
- class: "text-input",
- margin: "5px",
- placeholder: "# Cycles to add",
- type: "number",
- });
-
- const gangAddStoredCycles = createElement("button", {
- class: "std-button",
- clickListener: () => {
- try {
- const cycles = parseInt(gangStoredCyclesInput.value);
- Player.gang.storedCycles += cycles;
- } catch(e) {
- exceptionAlert(`Failed to add stored cycles to gang mechanic: ${e}`);
- }
- },
- innerText: "Add cycles to Gang mechanic",
- });
-
- // Corporation
- const corpHeader = createElement("h2", { innerText: "Corporation" });
-
- const corpStoredCyclesInput = createElement("input", {
- class: "text-input",
- margin: "5px",
- placeholder: "# Cycles to Add",
- type: "number",
- });
-
- const corpStoredCyclesButton = createElement("button", {
- class: "std-button",
- clickListener: () => {
- try {
- const cycles = parseInt(bladeburnerStoredCyclesInput.value);
- Player.corporation.storeCycles(cycles);
- } catch(e) {
- exceptionAlert(`Failed to add cycles to Bladeburner in dev menu: ${e}`);
- }
- },
- innerText: "Add Cycles to Corporation mechanic",
- });
-
- // Coding Contracts
- const contractsHeader = createElement("h2", {innerText: "Coding Contracts"});
-
- const generateRandomContractBtn = createElement("button", {
- class: "std-button",
- clickListener: () => {
- generateRandomContract();
- },
- innerText: "Generate Random Contract",
- });
-
- const generateRandomContractOnHomeBtn = createElement("button", {
- class: "std-button",
- clickListener: () => {
- generateRandomContractOnHome();
- },
- innerText: "Generate Random Contract on Home Comp",
- });
-
- const generateContractWithTypeSelector = createElement("select", { margin: "5px" });
- const contractTypes = Object.keys(CodingContractTypes);
- for (let i = 0; i < contractTypes.length; ++i) {
- generateContractWithTypeSelector.add(createOptionElement(contractTypes[i]));
- }
-
- const generateContractWithTypeBtn = createElement("button", {
- class: "std-button",
- clickListener: () => {
- generateContract({
- problemType: getSelectText(generateContractWithTypeSelector),
- server: "home",
- });
- },
- innerText: "Generate Specified Contract Type on Home Comp",
- });
-
- // Stock Market
- const stockmarketHeader = createElement("h2", {innerText: "Stock Market"});
-
- const stockInput = createElement("input", {
- class: "text-input",
- display: "block",
- placeholder: "Stock symbol(s), or 'all'",
- });
-
- function processStocks(cb) {
- const input = stockInput.value.toString().replace(/\s/g, '');
-
- // Empty input, or "all", will process all stocks
- if (input === "" || input.toLowerCase() === "all") {
- for (const name in StockMarket) {
- if (StockMarket.hasOwnProperty(name)) {
- const stock = StockMarket[name];
- if (stock instanceof Stock) {
- cb(stock);
- }
- }
- }
- return;
- }
-
- const stockSymbols = input.split(",");
- for (let i = 0; i < stockSymbols.length; ++i) {
- const stock = SymbolToStockMap[stockSymbols];
- if (stock instanceof Stock) {
- cb(stock);
- }
- }
- }
-
- const stockPriceChangeInput = createElement("input", {
- class: "text-input",
- margin: "5px",
- placeholder: "Price to change stock(s) to",
- type: "number",
- });
-
- const stockPriceChangeBtn = createElement("button", {
- class: "std-button",
- clickListener: () => {
- const price = parseInt(stockPriceChangeInput.value);
- if (isNaN(price)) { return; }
-
- processStocks((stock) => {
- stock.price = price;
- });
- dialogBoxCreate(`Stock Prices changed to ${price}`);
- },
- innerText: "Change Stock Price(s)",
- });
-
- const stockViewPriceCapBtn = createElement("button", {
- class: "std-button",
- clickListener: () => {
- let text = "";
- processStocks((stock) => {
- text += `${stock.symbol}: ${numeralWrapper.format(stock.cap, '$0.000a')}
`;
- });
- dialogBoxCreate(text);
- },
- innerText: "View Stock Price Caps",
- });
-
- // Sleeves
- const sleevesHeader = createElement("h2", { innerText: "Sleeves" });
-
- const sleevesRemoveAllShockRecovery = createElement("button", {
- class: "std-button",
- display: "block",
- innerText: "Set Shock Recovery of All Sleeves to 0",
- clickListener: () => {
- for (let i = 0; i < Player.sleeves.length; ++i) {
- Player.sleeves[i].shock = 100;
- }
- }
- });
-
- // Add everything to container, then append to main menu
- const devMenuContainer = createElement("div", {
- class: "generic-menupage-container",
- id: devMenuContainerId,
- });
-
- devMenuContainer.appendChild(devMenuText);
- devMenuContainer.appendChild(genericHeader);
- devMenuContainer.appendChild(addMoney);
- devMenuContainer.appendChild(addMoney2);
- devMenuContainer.appendChild(addRam);
- devMenuContainer.appendChild(triggerBitflume);
- devMenuContainer.appendChild(destroyCurrentBitnode);
- devMenuContainer.appendChild(statsHeader);
- devMenuContainer.appendChild(statsHackingExpInput);
- devMenuContainer.appendChild(statsHackingExpButton);
- devMenuContainer.appendChild(createElement("br"));
- devMenuContainer.appendChild(statsStrengthExpInput);
- devMenuContainer.appendChild(statsStrengthExpButton);
- devMenuContainer.appendChild(createElement("br"));
- devMenuContainer.appendChild(statsDefenseExpInput);
- devMenuContainer.appendChild(statsDefenseExpButton);
- devMenuContainer.appendChild(createElement("br"));
- devMenuContainer.appendChild(statsDexterityExpInput);
- devMenuContainer.appendChild(statsDexterityExpButton);
- devMenuContainer.appendChild(createElement("br"));
- devMenuContainer.appendChild(statsAgilityExpInput);
- devMenuContainer.appendChild(statsAgilityExpButton);
- devMenuContainer.appendChild(createElement("br"));
- devMenuContainer.appendChild(statsCharismaExpInput);
- devMenuContainer.appendChild(statsCharismaExpButton);
- devMenuContainer.appendChild(createElement("br"));
- devMenuContainer.appendChild(statsIntelligenceExpInput);
- devMenuContainer.appendChild(statsIntelligenceExpButton);
- devMenuContainer.appendChild(createElement("br"));
- devMenuContainer.appendChild(statsEnableIntelligenceButton);
- devMenuContainer.appendChild(statsDisableIntelligenceButton);
- devMenuContainer.appendChild(factionsHeader);
- devMenuContainer.appendChild(factionsDropdown);
- devMenuContainer.appendChild(factionsAddButton);
- devMenuContainer.appendChild(createElement("br"));
- devMenuContainer.appendChild(factionsReputationInput);
- devMenuContainer.appendChild(factionsReputationButton);
- devMenuContainer.appendChild(augmentationsHeader);
- devMenuContainer.appendChild(augmentationsDropdown);
- devMenuContainer.appendChild(augmentationsQueueButton);
- devMenuContainer.appendChild(giveAllAugmentationsButton);
- devMenuContainer.appendChild(sourceFilesHeader);
- devMenuContainer.appendChild(removeSourceFileDropdown);
- devMenuContainer.appendChild(removeSourceFileButton);
- devMenuContainer.appendChild(programsHeader);
- devMenuContainer.appendChild(programsAddDropdown);
- devMenuContainer.appendChild(programsAddButton);
- devMenuContainer.appendChild(serversHeader);
- devMenuContainer.appendChild(serversOpenAll);
- devMenuContainer.appendChild(serversMinSecurityAll);
- devMenuContainer.appendChild(serversMaxMoneyAll);
- devMenuContainer.appendChild(serversConnectToDropdown);
- devMenuContainer.appendChild(serversConnectToButton);
- devMenuContainer.appendChild(companiesHeader);
- devMenuContainer.appendChild(companiesDropdown);
- devMenuContainer.appendChild(createElement("br"));
- devMenuContainer.appendChild(companyReputationInput);
- devMenuContainer.appendChild(companyReputationButton);
- devMenuContainer.appendChild(bladeburnerHeader);
- devMenuContainer.appendChild(bladeburnerGainRankInput);
- devMenuContainer.appendChild(bladeburnerGainRankButton);
- devMenuContainer.appendChild(createElement("br"));
- devMenuContainer.appendChild(bladeburnerStoredCyclesInput);
- devMenuContainer.appendChild(bladeburnerStoredCyclesButton);
- devMenuContainer.appendChild(createElement("br"));
- devMenuContainer.appendChild(gangHeader);
- devMenuContainer.appendChild(gangStoredCyclesInput);
- devMenuContainer.appendChild(gangAddStoredCycles);
- devMenuContainer.appendChild(createElement("br"));
- devMenuContainer.appendChild(corpHeader);
- devMenuContainer.appendChild(corpStoredCyclesInput);
- devMenuContainer.appendChild(corpStoredCyclesButton);
- devMenuContainer.appendChild(createElement("br"));
- devMenuContainer.appendChild(contractsHeader);
- devMenuContainer.appendChild(generateRandomContractBtn);
- devMenuContainer.appendChild(generateRandomContractOnHomeBtn);
- devMenuContainer.appendChild(createElement("br"));
- devMenuContainer.appendChild(generateContractWithTypeSelector);
- devMenuContainer.appendChild(generateContractWithTypeBtn);
- devMenuContainer.appendChild(stockmarketHeader);
- devMenuContainer.appendChild(stockInput);
- devMenuContainer.appendChild(stockPriceChangeInput);
- devMenuContainer.appendChild(stockPriceChangeBtn);
- devMenuContainer.appendChild(createElement("br"));
- devMenuContainer.appendChild(stockViewPriceCapBtn);
- devMenuContainer.appendChild(sleevesHeader);
- devMenuContainer.appendChild(sleevesRemoveAllShockRecovery);
-
- const entireGameContainer = document.getElementById("entire-game-container");
- if (entireGameContainer == null) {
- throw new Error("Could not find entire-game-container DOM element");
- }
- entireGameContainer.appendChild(devMenuContainer);
-}
-
-export function closeDevMenu() {
- removeElementById(devMenuContainerId);
-}
diff --git a/src/DevMenu.jsx b/src/DevMenu.jsx
new file mode 100644
index 000000000..4b3417d79
--- /dev/null
+++ b/src/DevMenu.jsx
@@ -0,0 +1,1213 @@
+import { AugmentationNames } from "./Augmentation/data/AugmentationNames";
+import { CodingContractTypes } from "./CodingContracts";
+import { generateContract,
+ generateRandomContract,
+ generateRandomContractOnHome } from "./CodingContractGenerator";
+import { Companies } from "./Company/Companies";
+import { Company } from "./Company/Company";
+import { Programs } from "./Programs/Programs";
+import { Factions } from "./Faction/Factions";
+import { Player } from "./Player";
+import { PlayerOwnedSourceFile } from "./SourceFile/PlayerOwnedSourceFile";
+import { AllServers } from "./Server/AllServers";
+import { GetServerByHostname } from "./Server/ServerHelpers";
+import { hackWorldDaemon } from "./RedPill";
+import { StockMarket,
+ SymbolToStockMap } from "./StockMarket/StockMarket";
+import { Stock } from "./StockMarket/Stock";
+import { Terminal } from "./Terminal";
+
+import { numeralWrapper } from "./ui/numeralFormat";
+
+import { dialogBoxCreate } from "../utils/DialogBox";
+import { exceptionAlert } from "../utils/helpers/exceptionAlert";
+import { createElement } from "../utils/uiHelpers/createElement";
+import { createOptionElement } from "../utils/uiHelpers/createOptionElement";
+import { getSelectText } from "../utils/uiHelpers/getSelectData";
+import { removeElementById } from "../utils/uiHelpers/removeElementById";
+
+import React from "react";
+import ReactDOM from "react-dom";
+
+const Component = React.Component;
+
+const validSFN = [1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12];
+
+
+class ValueAdjusterComponent extends Component {
+ constructor(props) {
+ super(props);
+ this.state = { value: '' };
+ this.setValue = this.setValue.bind(this);
+ }
+ setValue(event) {
+ this.setState({ value: event.target.value });
+ }
+ render() {
+ const { title, add, subtract, reset } = this.props;
+ const { value } = this.state;
+ return (
+ <>
+
+
+
+
+ >
+ );
+ }
+}
+
+class DevMenuComponent extends Component {
+ constructor(props) {
+ super(props);
+ this.state = {
+ company: 'ECorp',
+ faction: 'Illuminati',
+ program: 'NUKE.exe',
+ server: 'home',
+ augmentation: 'Augmented Targeting I',
+ codingcontract: 'Find Largest Prime Factor',
+ }
+
+ this.setSF = this.setSF.bind(this);
+ this.setAllSF = this.setAllSF.bind(this);
+ this.processStocks = this.processStocks.bind(this);
+ this.setStockPrice = this.setStockPrice.bind(this);
+ this.viewStockCaps = this.viewStockCaps.bind(this);
+
+ this.setFactionDropdown = this.setFactionDropdown.bind(this);
+ this.setCompanyDropdown = this.setCompanyDropdown.bind(this);
+ this.setProgramDropdown = this.setProgramDropdown.bind(this);
+ this.setServerDropdown = this.setServerDropdown.bind(this);
+ this.setAugmentationDropdown = this.setAugmentationDropdown.bind(this);
+ this.setCodingcontractDropdown = this.setCodingcontractDropdown.bind(this);
+
+ this.receiveInvite = this.receiveInvite.bind(this);
+ this.modifyFactionRep = this.modifyFactionRep.bind(this);
+ this.resetFactionRep = this.resetFactionRep.bind(this);
+ this.modifyFactionFavor = this.modifyFactionFavor.bind(this);
+ this.resetFactionFavor = this.resetFactionFavor.bind(this);
+ this.queueAug = this.queueAug.bind(this);
+ this.addProgram = this.addProgram.bind(this);
+ this.rootServer = this.rootServer.bind(this);
+ this.minSecurity = this.minSecurity.bind(this);
+ this.maxMoney = this.maxMoney.bind(this);
+ this.modifyCompanyRep = this.modifyCompanyRep.bind(this);
+ this.resetCompanyRep = this.resetCompanyRep.bind(this);
+ this.modifyCompanyFavor = this.modifyCompanyFavor.bind(this);
+ this.resetCompanyFavor = this.resetCompanyFavor.bind(this);
+ this.specificContract = this.specificContract.bind(this);
+ }
+
+ setFactionDropdown(event) {
+ this.setState({ faction: event.target.value });
+ }
+
+ setCompanyDropdown(event) {
+ this.setState({ company: event.target.value });
+ }
+
+ setProgramDropdown(event) {
+ this.setState({ program: event.target.value });
+ }
+
+ setServerDropdown(event) {
+ this.setState({ server: event.target.value });
+ }
+
+ setAugmentationDropdown(event) {
+ this.setState({ augmentation: event.target.value });
+ }
+
+ setCodingcontractDropdown(event) {
+ this.setState({ codingcontract: event.target.value });
+ }
+
+
+ addMoney(n) {
+ return function() {
+ Player.gainMoney(n);
+ }
+ }
+
+ upgradeRam() {
+ Player.getHomeComputer().maxRam *= 2;
+ }
+
+ b1tflum3() {
+ hackWorldDaemon(Player.bitNodeN, true);
+ }
+
+ hackW0r1dD43m0n() {
+ hackWorldDaemon(Player.bitNodeN);
+ }
+
+ modifyExp(stat, modifier) {
+ return function(exp) {
+ switch(stat) {
+ case "hacking":
+ if(exp) {
+ Player.gainHackingExp(exp*modifier);
+ }
+ break;
+ case "strength":
+ if(exp) {
+ Player.gainStrengthExp(exp*modifier);
+ }
+ break;
+ case "defense":
+ if(exp) {
+ Player.gainDefenseExp(exp*modifier);
+ }
+ break;
+ case "dexterity":
+ if(exp) {
+ Player.gainDexterityExp(exp*modifier);
+ }
+ break;
+ case "agility":
+ if(exp) {
+ Player.gainAgilityExp(exp*modifier);
+ }
+ break;
+ case "charisma":
+ if(exp) {
+ Player.gainCharismaExp(exp*modifier);
+ }
+ break;
+ case "intelligence":
+ if(exp) {
+ Player.gainIntelligenceExp(exp*modifier);
+ }
+ break;
+ }
+ Player.updateSkillLevels();
+ }
+ }
+
+ tonsOfExp() {
+ Player.gainHackingExp(1e27);
+ Player.gainStrengthExp(1e27);
+ Player.gainDefenseExp(1e27);
+ Player.gainDexterityExp(1e27);
+ Player.gainAgilityExp(1e27);
+ Player.gainCharismaExp(1e27);
+ Player.gainIntelligenceExp(1e27);
+ Player.updateSkillLevels();
+ }
+
+ resetAllExp() {
+ Player.hacking_exp = 0;
+ Player.strength_exp = 0;
+ Player.defense_exp = 0;
+ Player.dexterity_exp = 0;
+ Player.agility_exp = 0;
+ Player.charisma_exp = 0;
+ Player.intelligence_exp = 0;
+ Player.updateSkillLevels();
+ }
+
+ resetExperience(stat) {
+ return function() {
+ switch(stat) {
+ case "hacking":
+ Player.hacking_exp = 0;
+ break;
+ case "strength":
+ Player.strength_exp = 0;
+ break;
+ case "defense":
+ Player.defense_exp = 0;
+ break;
+ case "dexterity":
+ Player.dexterity_exp = 0;
+ break;
+ case "agility":
+ Player.agility_exp = 0;
+ break;
+ case "charisma":
+ Player.charisma_exp = 0;
+ break;
+ case "intelligence":
+ Player.intelligence_exp = 0;
+ break;
+ }
+ Player.updateSkillLevels();
+ }
+ }
+
+ enableIntelligence() {
+ if(Player.intelligence === 0) {
+ Player.intelligence = 1;
+ Player.updateSkillLevels();
+ }
+ }
+
+ disableIntelligence() {
+ Player.intelligence_exp = 0;
+ Player.intelligence = 0;
+ Player.updateSkillLevels();
+ }
+
+ receiveInvite() {
+ Player.receiveInvite(this.state.faction);
+ }
+
+ receiveAllInvites() {
+ for (const i in Factions) {
+ Player.receiveInvite(Factions[i].name);
+ }
+ }
+
+ modifyFactionRep(modifier) {
+ const component = this;
+ return function(reputation) {
+ const fac = Factions[component.state.faction];
+ if (fac != null && !isNaN(reputation)) {
+ fac.playerReputation += reputation*modifier;
+ }
+ }
+ }
+
+ resetFactionRep() {
+ const fac = Factions[this.state.faction];
+ if (fac != null) {
+ fac.playerReputation = 0;
+ }
+ }
+
+ modifyFactionFavor(modifier) {
+ const component = this;
+ return function(favor) {
+ const fac = Factions[component.state.faction];
+ if (fac != null && !isNaN(favor)) {
+ fac.favor += favor*modifier;
+ }
+ }
+ }
+
+ resetFactionFavor() {
+ const fac = Factions[this.state.faction];
+ if (fac != null) {
+ fac.favor = 0;
+ }
+ }
+
+ tonsOfRep() {
+ for (const i in Factions) {
+ Factions[i].playerReputation = 1e27;
+ }
+ }
+
+ resetAllRep() {
+ for (const i in Factions) {
+ Factions[i].playerReputation = 0;
+ }
+ }
+
+ tonsOfFactionFavor() {
+ for (const i in Factions) {
+ Factions[i].favor = 1e27;
+ }
+ }
+
+ resetAllFactionFavor() {
+ for (const i in Factions) {
+ Factions[i].favor = 0;
+ }
+ }
+
+ queueAug() {
+ Player.queueAugmentation(this.state.augmentation);
+ }
+
+ queueAllAugs() {
+ for (const i in AugmentationNames) {
+ const augName = AugmentationNames[i];
+ Player.queueAugmentation(augName);
+ }
+ }
+
+ setSF(sfN, sfLvl) {
+ return function() {
+ if (sfLvl === 0) {
+ Player.sourceFiles = Player.sourceFiles.filter((sf) => sf.n !== sfN);
+ return;
+ }
+
+ if(!Player.sourceFiles.some((sf) => sf.n === sfN)) {
+ Player.sourceFiles.push(new PlayerOwnedSourceFile(sfN, sfLvl));
+ return;
+ }
+
+ for(let i = 0; i < Player.sourceFiles.length; i++) {
+ if (Player.sourceFiles[i].n === sfN) {
+ Player.sourceFiles[i].lvl = sfLvl;
+ }
+ }
+ }
+ }
+
+ setAllSF(sfLvl) {
+ const component = this;
+ return function(){
+ for (let i = 0; i < validSFN.length; i++) {
+ component.setSF(validSFN[i], sfLvl)();
+ }
+ }
+ }
+
+ addProgram() {
+ const program = this.state.program;
+ if(!Player.hasProgram(program)) {
+ Player.getHomeComputer().programs.push(program);
+ }
+ }
+
+ addAllPrograms() {
+ for (const i in Programs) {
+ if(!Player.hasProgram(Programs[i].name)) {
+ Player.getHomeComputer().programs.push(Programs[i].name);
+ }
+ }
+ }
+
+ rootServer() {
+ const serverName = this.state.server;
+ const server = GetServerByHostname(serverName);
+
+ server.hasAdminRights = true;
+ server.sshPortOpen = true;
+ server.ftpPortOpen = true;
+ server.smtpPortOpen = true;
+ server.httpPortOpen = true;
+ server.sqlPortOpen = true;
+ server.openPortCount = 5;
+ }
+
+ rootAllServers() {
+ for (const i in AllServers) {
+ AllServers[i].hasAdminRights = true;
+ AllServers[i].sshPortOpen = true;
+ AllServers[i].ftpPortOpen = true;
+ AllServers[i].smtpPortOpen = true;
+ AllServers[i].httpPortOpen = true;
+ AllServers[i].sqlPortOpen = true;
+ AllServers[i].openPortCount = 5;
+ }
+ }
+
+ minSecurity() {
+ const serverName = this.state.server;
+ const server = GetServerByHostname(serverName);
+ server.hackDifficulty = server.minDifficulty;
+ }
+
+ minAllSecurity() {
+ for (const i in AllServers) {
+ AllServers[i].hackDifficulty = AllServers[i].minDifficulty;
+ }
+ }
+
+ maxMoney() {
+ const serverName = this.state.server;
+ const server = GetServerByHostname(serverName);
+ server.moneyAvailable = server.moneyMax;
+ }
+
+ maxAllMoney() {
+ for (const i in AllServers) {
+ AllServers[i].moneyAvailable = AllServers[i].moneyMax;
+ }
+ }
+
+ modifyCompanyRep(modifier) {
+ const component = this;
+ return function(reputation) {
+ const company = Companies[component.state.company];
+ if (company != null && !isNaN(reputation)) {
+ company.playerReputation += reputation*modifier;
+ }
+ }
+ }
+
+ resetCompanyRep() {
+ const company = Companies[this.state.company];
+ company.playerReputation = 0;
+ }
+
+ modifyCompanyFavor(modifier) {
+ const component = this;
+ return function(favor) {
+ const company = Companies[component.state.company];
+ if (company != null && !isNaN(favor)) {
+ company.favor += favor*modifier;
+ }
+ }
+ }
+
+ resetCompanyFavor() {
+ const company = Companies[this.state.company];
+ company.favor = 0;
+ }
+
+ tonsOfRepCompanies() {
+ for (const c in Companies) {
+ Companies[c].playerReputation = 1e12;
+ }
+ }
+
+ resetAllRepCompanies() {
+ for (const c in Companies) {
+ Companies[c].playerReputation = 0;
+ }
+ }
+
+ tonsOfFavorCompanies() {
+ for (const c in Companies) {
+ Companies[c].favor = 1e12;
+ }
+ }
+
+ resetAllFavorCompanies() {
+ for (const c in Companies) {
+ Companies[c].favor = 0;
+ }
+ }
+
+ modifyBladeburnerRank(modify) {
+ return function(rank) {
+ if (!!Player.bladeburner) {
+ Player.bladeburner.changeRank(rank*modify);
+ }
+ }
+ }
+
+ resetBladeburnerRank() {
+ Player.bladeburner.rank = 0;
+ Player.bladeburner.maxRank = 0;
+ }
+
+ addTonsBladeburnerRank() {
+ if (!!Player.bladeburner) {
+ Player.bladeburner.changeRank(1e12);
+ }
+ }
+
+ modifyBladeburnerCycles(modify) {
+ return function(cycles) {
+ if (!!Player.bladeburner) {
+ Player.bladeburner.storedCycles += cycles*modify;
+ }
+ }
+ }
+
+ resetBladeburnerCycles() {
+ if (!!Player.bladeburner) {
+ Player.bladeburner.storedCycles = 0;
+ }
+ }
+
+ addTonsBladeburnerCycles() {
+ if (!!Player.bladeburner) {
+ Player.bladeburner.storedCycles += 1e12;
+ }
+ }
+
+ addTonsGangCycles() {
+ if (!!Player.gang) {
+ Player.gang.storedCycles = 1e12;
+ }
+ }
+
+ modifyGangCycles(modify) {
+ return function(cycles) {
+ if (!!Player.gang) {
+ Player.gang.storedCycles += cycles*modify;
+ }
+ }
+ }
+
+ resetGangCycles() {
+ if (!!Player.gang) {
+ Player.gang.storedCycles = 0;
+ }
+ }
+
+ addTonsCorporationCycles() {
+ if (!!Player.corporation) {
+ Player.corporation.storedCycles = 1e12;
+ }
+ }
+
+ modifyCorporationCycles(modify) {
+ return function(cycles) {
+ if (!!Player.corporation) {
+ Player.corporation.storedCycles += cycles*modify;
+ }
+ }
+ }
+
+ resetCorporationCycles() {
+ if (!!Player.corporation) {
+ Player.corporation.storedCycles = 0;
+ }
+ }
+
+ specificContract() {
+ generateContract({
+ problemType: this.state.codingcontract,
+ server: "home",
+ });
+ }
+
+ processStocks(cb) {
+ const inputSymbols = document.getElementById('dev-stock-symbol').value.toString().replace(/\s/g, '');
+
+ let match = function(symbol) { return true; }
+
+ if (inputSymbols !== '' && inputSymbols !== 'all') {
+ match = function(symbol) {
+ return inputSymbols.split(',').includes(symbol);
+ };
+ }
+
+ for (const name in StockMarket) {
+ if (StockMarket.hasOwnProperty(name)) {
+ const stock = StockMarket[name];
+ if (stock instanceof Stock && match(stock.symbol)) {
+ cb(stock);
+ }
+ }
+ }
+ }
+
+ setStockPrice() {
+ const price = parseFloat(document.getElementById('dev-stock-price').value);
+
+ if (!isNaN(price)) {
+ this.processStocks((stock) => {
+ stock.price = price;
+ });
+ }
+ }
+
+ viewStockCaps() {
+ let text = "
| Stock | Price cap |
";
+ this.processStocks((stock) => {
+ text += `| ${stock.symbol} | ${numeralWrapper.format(stock.cap, '$0.000a')} |
`;
+ });
+ text += "
";
+ dialogBoxCreate(text);
+ }
+
+ sleeveMaxAllShock() {
+ for (let i = 0; i < Player.sleeves.length; ++i) {
+ Player.sleeves[i].shock = 0;
+ }
+ }
+
+ sleeveClearAllShock() {
+ for (let i = 0; i < Player.sleeves.length; ++i) {
+ Player.sleeves[i].shock = 100;
+ }
+ }
+
+ sleeveMaxAllSync() {
+ for (let i = 0; i < Player.sleeves.length; ++i) {
+ Player.sleeves[i].sync = 100;
+ }
+ }
+
+ sleeveClearAllSync() {
+ for (let i = 0; i < Player.sleeves.length; ++i) {
+ Player.sleeves[i].sync = 0;
+ }
+ }
+
+ render() {
+ let factions = [];
+ for (const i in Factions) {
+ factions.push();
+ }
+
+ let augs = [];
+ for (const i in AugmentationNames) {
+ augs.push();
+ }
+
+ let programs = [];
+ for (const i in Programs) {
+ programs.push();
+ }
+
+ let sourceFiles = [];
+ validSFN.forEach( i => sourceFiles.push(
+
+ | SF-{i}: |
+
+
+
+
+
+ |
+
+));
+
+
+
+ let servers = [];
+ for (const i in AllServers) {
+ const hn = AllServers[i].hostname;
+ servers.push();
+ }
+
+ let companies = [];
+ for (const c in Companies) {
+ const name = Companies[c].name;
+ companies.push();
+ }
+
+ const contractTypes = [];
+ const contractTypeNames = Object.keys(CodingContractTypes)
+ for (let i = 0; i < contractTypeNames.length; i++) {
+ const name = contractTypeNames[i];
+ contractTypes.push();
+ }
+
+
+ return (
+
+
+
Development Menu - Only meant to be used for testing/debugging
+
+
+
Generic
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Experience / Stats
+
+
+
+
+ | All: |
+
+
+
+ |
+
+
+ |
+ Hacking:
+ |
+
+
+ |
+
+
+ |
+ Strength:
+ |
+
+
+ |
+
+
+ |
+ Defense:
+ |
+
+
+ |
+
+
+ |
+ Dexterity:
+ |
+
+
+ |
+
+
+ |
+ Agility:
+ |
+
+
+ |
+
+
+ |
+ Charisma:
+ |
+
+
+ |
+
+
+ |
+ Intelligence:
+ |
+
+
+ |
+
+
+ |
+
+
+ |
+
+
+
+
+
+
+
+
+
Factions
+
+
+
+
+ | Faction: |
+ |
+
+
+ | Invites: |
+ |
+ |
+
+
+ |
+ Reputation:
+ |
+
+
+ |
+
+
+ |
+ Favor:
+ |
+
+
+ |
+
+
+ | All Reputation: |
+
+
+
+ |
+
+
+ | All Favor: |
+
+
+
+ |
+
+
+
+
+
+
+
+
+
+
Augmentations
+
+
+
+
+ | Aug: |
+ |
+
+
+ | Queue: |
+
+ |
+
+
+
+
+
+
+
+
+
Source-Files
+
+
+
+
+ | All: |
+
+
+
+
+
+ |
+
+ {sourceFiles}
+
+
+
+
+
+
+
+
Programs
+
+
+
+
+ | Program: |
+ |
+
+
+ | Add: |
+
+
+
+ |
+
+
+
+
+
+
+
+
+
Servers
+
+
+
+
+ | Server: |
+ |
+
+
+ | Root: |
+ |
+ |
+
+
+ | Security: |
+ |
+ |
+
+
+ | Money: |
+ |
+ |
+
+
+
+
+
+
+
+
+
Companies
+
+
+
+
+ | Company: |
+ |
+
+
+ | Reputation: |
+
+
+ |
+
+
+ | Favor: |
+
+
+ |
+
+
+ | All Reputation: |
+
+
+
+ |
+
+
+ | All Favor: |
+
+
+
+ |
+
+
+
+
+
+
+
+
+
+
Bladeburner
+
+
+
+
+ | Rank: |
+ |
+
+
+ |
+
+
+ | Cycles: |
+ |
+
+
+ |
+
+
+
+
+
+
+
+
+
+
Gang
+
+
+
+
+ | Cycles: |
+ |
+
+
+ |
+
+
+
+
+
+
+
+
+
+
Corporation
+
+
+
+
+ | Cycles: |
+ |
+
+
+ |
+
+
+
+
+
+
+
+
+
+
+
Coding Contracts
+
+
+
+
+ |
+
+
+ |
+
+
+ |
+
+
+
+ |
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Sleeves
+
+
+
+
+ | Shock: |
+ |
+ |
+
+
+ | Sync: |
+ |
+ |
+
+
+
+
+
+
+
+ );
+ }
+}
+
+
+const devMenuContainerId = "dev-menu-container";
+
+export function createDevMenu() {
+ if (process.env.NODE_ENV !== "development") {
+ throw new Error("Cannot create Dev Menu because you are not in a dev build");
+ }
+
+ // Add everything to container, then append to main menu
+ const devMenuContainer = createElement("div", {
+ class: "generic-menupage-container",
+ id: devMenuContainerId,
+ });
+
+ const entireGameContainer = document.getElementById("entire-game-container");
+ if (entireGameContainer == null) {
+ throw new Error("Could not find entire-game-container DOM element");
+ }
+ entireGameContainer.appendChild(devMenuContainer);
+
+ ReactDOM.render(, devMenuContainer);
+}
+
+export function closeDevMenu() {
+ removeElementById(devMenuContainerId);
+}
diff --git a/src/Faction/FactionHelpers.js b/src/Faction/FactionHelpers.js
index bf5ee423f..c061c359c 100644
--- a/src/Faction/FactionHelpers.js
+++ b/src/Faction/FactionHelpers.js
@@ -199,7 +199,7 @@ function displayFactionContent(factionName) {
innerText:"This donation will result in 0.000 reputation gain"
});
var donateAmountInput = createElement("input", {
- placeholder:"Donation amount",
+ class: "text-input", placeholder:"Donation amount",
inputListener:()=>{
let amt = 0;
if(donateAmountInput.value !== "") {
diff --git a/src/PersonObjects/Sleeve/SleeveUI.ts b/src/PersonObjects/Sleeve/SleeveUI.ts
index cf8ef9cf4..e7daf6d55 100644
--- a/src/PersonObjects/Sleeve/SleeveUI.ts
+++ b/src/PersonObjects/Sleeve/SleeveUI.ts
@@ -288,7 +288,7 @@ function createSleeveUi(sleeve: Sleeve, allSleeves: Sleeve[]): ISleeveUIElems {
}
elems.taskPanel = createElement("div", { class: "sleeve-panel", width: "40%" });
- elems.taskSelector = createElement("select") as HTMLSelectElement;
+ elems.taskSelector = createElement("select", { class: "dropdown" }) as HTMLSelectElement;
elems.taskSelector.add(createOptionElement("------"));
elems.taskSelector.add(createOptionElement("Work for Company"));
elems.taskSelector.add(createOptionElement("Work for Faction"));
@@ -297,8 +297,8 @@ function createSleeveUi(sleeve: Sleeve, allSleeves: Sleeve[]): ISleeveUIElems {
elems.taskSelector.add(createOptionElement("Workout at Gym"));
elems.taskSelector.add(createOptionElement("Shock Recovery"));
elems.taskSelector.add(createOptionElement("Synchronize"));
- elems.taskDetailsSelector = createElement("select") as HTMLSelectElement;
- elems.taskDetailsSelector2 = createElement("select") as HTMLSelectElement;
+ elems.taskDetailsSelector = createElement("select", { class: "dropdown" }) as HTMLSelectElement;
+ elems.taskDetailsSelector2 = createElement("select", { class: "dropdown" }) as HTMLSelectElement;
elems.taskDescription = createElement("p");
elems.taskProgressBar = createElement("p");
elems.taskSelector.addEventListener("change", () => {
diff --git a/src/StockMarket/StockMarket.js b/src/StockMarket/StockMarket.js
index 8b9f756b1..d7b57d991 100644
--- a/src/StockMarket/StockMarket.js
+++ b/src/StockMarket/StockMarket.js
@@ -175,6 +175,11 @@ let StockMarket = {} //Full name to stock object
let StockSymbols = {} //Full name to symbol
let SymbolToStockMap = {}; //Symbol to Stock object
+let formatHelpData = {
+ longestName: 0,
+ longestSymbol: 0,
+};
+
function loadStockMarket(saveString) {
if (saveString === "") {
StockMarket = {};
@@ -220,6 +225,12 @@ function initStockSymbols() {
StockSymbols["Catalyst Ventures"] = "CTYS";
StockSymbols["Microdyne Technologies"] = "MDYN";
StockSymbols["Titan Laboratories"] = "TITN";
+
+ for (const key in StockSymbols) {
+ formatHelpData.longestName = key.length > formatHelpData.longestName ? key.length : formatHelpData.longestName;
+ formatHelpData.longestSymbol = StockSymbols[key].length > formatHelpData.longestSymbol ? StockSymbols[key].length : formatHelpData.longestSymbol;
+ }
+ console.log(formatHelpData);
}
function initStockMarket() {
@@ -1070,10 +1081,11 @@ function createStockTicker(stock) {
return;
}
var tickerId = "stock-market-ticker-" + stock.symbol;
- var li = document.createElement("li"), hdr = document.createElement("button");
+ var li = document.createElement("li"), hdr = document.createElement("button"), hdrpre = document.createElement("pre");;
hdr.classList.add("accordion-header");
hdr.setAttribute("id", tickerId + "-hdr");
- hdr.innerHTML = stock.name + " - " + stock.symbol + " - " + numeralWrapper.format(stock.price, '($0.000a)');
+ hdrpre.textContent = stock.name + " - " + stock.symbol + " - " + numeralWrapper.format(stock.price, '($0.000a)');
+ hdr.appendChild(hdrpre);
//Div for entire panel
var stockDiv = document.createElement("div");
@@ -1352,19 +1364,15 @@ function updateStockTicker(stock, increase) {
}
return;
}
- let hdrText = stock.name + " (" + stock.symbol + ") - " + numeralWrapper.format(stock.price, '($0.000a)');
+ const stockPriceFormat = numeralWrapper.format(stock.price, '($0.000a)')
+ let hdrText = `${stock.name}${" ".repeat(1 + formatHelpData.longestName - stock.name.length + (formatHelpData.longestSymbol-stock.symbol.length))}${stock.symbol} -${" ".repeat(10 - stockPriceFormat.length)}${stockPriceFormat}`;
if (Player.has4SData) {
- hdrText += " - Volatility: " + numeralWrapper.format(stock.mv, '0,0.00') + "%" +
- " - Price Forecast: ";
- if (stock.b) {
- hdrText += "+".repeat(Math.floor(stock.otlkMag/10) + 1);
- } else {
- hdrText += "-".repeat(Math.floor(stock.otlkMag/10) + 1);
- }
+ hdrText += ` - Volatility: ${numeralWrapper.format(stock.mv, '0,0.00')}% - Price Forecast: `;
+ hdrText += (stock.b?"+":"-").repeat(Math.floor(stock.otlkMag/10) + 1);
}
- hdr.innerText = hdrText;
+ hdr.firstChild.textContent = hdrText;
if (increase != null) {
- increase ? hdr.style.color = "#66ff33" : hdr.style.color = "red";
+ hdr.firstChild.style.color = increase ? "#66ff33" : "red";
}
}
diff --git a/src/engine.jsx b/src/engine.jsx
index 8b0646aa8..87d8fffe4 100644
--- a/src/engine.jsx
+++ b/src/engine.jsx
@@ -124,6 +124,8 @@ import "../css/gang.scss";
import "../css/sleeves.scss";
import "../css/resleeving.scss";
import "../css/treant.css";
+import "../css/grid.min.css";
+import "../css/dev-menu.css";
/* Shortcuts to navigate through the game
diff --git a/src/index.html b/src/index.html
index 5dd72486b..63670a198 100644
--- a/src/index.html
+++ b/src/index.html
@@ -702,7 +702,7 @@ if (htmlWebpackPlugin.options.googleAnalytics.trackingId) { %>
Expand tickers
Collapse tickers
-
+
Update Watchlist