http://45.5.151.151:8000/

Last Checked: Mar 03, 2024, 10:34 EST

IP Address: 45.5.151.151
ASN #: AS265702 AZUL NETWORKS S.R.L, AR
Location: Unknown, Unknown, Unknown
URL Reputation:
  • Unknown This URL is not identified as malicious in the PhishTank Database.
  • Unknown PhishCheck thinks this URL is likely not a phish.
  • Unknown OpenPhish: URL not in feed.

Other submissions on 45.5.151.151:

Other submissions on 45.5.151.151:

Previous checks:

  • Apr 21, 2024, 07:46 EDT

                               % IP Client: 142.93.23.27
 
% Joint Whois - whois.lacnic.net
%  This server accepts single ASN, IPv4 or IPv6 queries

% LACNIC resource: whois.lacnic.net


% Copyright LACNIC lacnic.net
%  The data below is provided for information purposes
%  and to assist persons in obtaining information about or
%  related to AS and IP numbers registrations
%  By submitting a whois query, you agree to use this data
%  only for lawful purposes.
%  2024-03-03 12:34:42 (-03 -03:00)

inetnum:     45.5.148.0/22
status:      allocated
aut-num:     AS265702
owner:       AZUL NETWORKS S.R.L
ownerid:     AR-ANSR7-LACNIC
responsible: David Sebastián Ramires
address:     Illia, 369, -
address:     4600 - San Salvador de Jujuy - 
country:     AR
phone:       +54  3884392879 [0000]
owner-c:     DSR12
tech-c:      DSR12
abuse-c:     DSR12
inetrev:     45.5.148.0/22
nserver:     ISAAC.NS.CLOUDFLARE.COM
nsstat:      20240302 AA
nslastaa:    20240302
nserver:     JESSICA.NS.CLOUDFLARE.COM
nsstat:      20240302 AA
nslastaa:    20240302
created:     20170410
changed:     20210916

nic-hdl:     DSR12
person:      David Sebastian Ramires
e-mail:      davidsramires@gmail.com
address:     El Clavel, 82, Barrio Chijra
address:     4600 - San Salvador de Jujuy - Jujuy
country:     AR
phone:       +54  3884392879 [0000]
created:     20180307
changed:     20220320

% whois.lacnic.net accepts only direct match queries.
% Types of queries are: POCs, ownerid, CIDR blocks, IP
% and AS numbers.


                             
  • POST
    0 Timed out waiting for a response.

    http://45.5.151.151:8000/control/

<html lang="en"><head>
    <title>Astra Control Panel</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
    <link rel="icon" type="image/png" href="/favicon.png">
    <style>
/* Astra: Web Interface */
/* https://cesbo.com/astra/ */
/* Copyright (C) 2012-2023, Cesbo OU <info@cesbo.com> */

/* pony.css */

:root {
	--main-bg-color: hsl(220, 10%, 100%);
	--border-color: hsl(220, 10%, 80%);
	--main-menu-background: hsl(220, 10%, 95%);
	--backdrop-color: #000;
	--text-color: hsl(220, 10%, 20%);
	--link-color: hsl(200, 60%, 50%);
	--hover-bg-color: hsl(200, 60%, 95%);
	--info-color: hsl(200, 60%, 30%);
	--info-bg-color: hsl(200, 60%, 90%);
	--error-color: hsl(0, 60%, 30%);
	--error-bg-color: hsl(0, 60%, 90%);
	--warning-color: hsl(40, 60%, 60%);
	--warning-bg-color: hsl(40, 60%, 90%);
	--inactive-color: hsl(220, 10%, 40%);
	--error-bright-color: hsl(0, 60%, 50%);
	--warning-bright-color: hsl(40, 60%, 50%);
	--success-bright-color: hsl(140, 60%, 50%);
	--error-bright-color-dark: hsl(0, 60%, 10%);
	--success-bright-color-dark: hsl(140, 60%, 10%);
	--menu-icon-width: 44px;
	--menu-icon-size: 24px;
	--menu-icon-color: var(--text-color);
	--menu-arrow-size: 20px;
	--menu-arrow-color: var(--border-color);
	--border-radius: .2em;
    /* Desktop */
	--main-menu-background-color: hsl(220, 10%, 94%);
	--main-menu-close-background-color: var(--main-menu-background-color);
	--main-menu-height: 100%;
	--main-menu-open-width: 240px;
	--main-menu-open-height: 100%;
	--main-nemu-open-by-hands-position: relative;
	--menu-item-height: 32px;
	--menu-item-hover-color: var(--hover-bg-color);
	--menu-item-box-shadow: 0 0 4px 0 var(--border-color);
}

.dark {
	--main-bg-color: hsl(220, 10%, 20%);
	--border-color: hsl(220, 10%, 30%);
	--main-menu-background-color: hsl(220, 10%, 25%);
	--backdrop-color: #fff;
	--text-color: hsl(0, 0%, 80%);
	--link-color: hsl(200, 60%, 50%);
	--hover-bg-color: hsl(220, 10%, 30%);
	--inactive-color: hsl(220, 10%, 60%);
	--error-bright-color: hsl(0, 80%, 60%);
	--warning-bright-color: hsl(40, 80%, 60%);
	--success-bright-color: hsl(140, 80%, 60%);
}

body,html {
	margin: 0;
	padding: 0;
	display: block;
}

html {
	height: 0;
	-ms-text-size-adjust: 100%;
	-webkit-text-size-adjust: 100%;
}

body {
	font: 14px "Helvetica Neue", Helvetica, Arial, sans-serif;
	color: var(--text-color);
}

body,div {
	background-color: var(--main-bg-color);
}

*,:after,:before {
	-moz-box-sizing: border-box;
	-webkit-box-sizing: border-box;
	box-sizing: border-box;
}

[disabled] {
	cursor: not-allowed !important;
}

.hide {
	display: none !important;
}

.main-menu {
	display: -webkit-flex;
	display: flex;
	border-bottom: 1px solid var(--border-color);
	z-index: 1000;
	overflow-x: auto;
}

.main-menu>* {
	display: inline-block;
	-webkit-flex: 0 0 auto;
	flex: 0 0 auto;
	font-size: 16px;
	padding: 0 10px;
	font-weight: 200;
	line-height: 30px;
}

.main-menu>a {
	text-decoration: none;
	outline: 0;
}

.main-menu>a.active,.main-menu>a:focus,.main-menu>a:hover {
	background-color: var(--hover-bg-color);
	text-decoration: none;
}

.main-menu>a.active {
	cursor: default;
}

.main-menu>.search {
	-webkit-flex: 2 0 auto;
	flex: 2 0 auto;
}

.main-menu>.search.input {
	font-size: 16px;
	font-weight: 200;
	outline: 0;
	border: 0;
	height: 30px;
	width: auto;
}

.main-menu>.search.input:focus {
	box-shadow: none;
}

.main-menu>hr {
	padding: 0;
}

.main-menu.fixed {
	position: fixed;
	top: 0;
	left: 0;
	width: 100%;
}

.main-menu.fixed+.main-content {
	padding-top: 30px;
}

.main-menu.modal {
	-webkit-flex-direction: column;
	flex-direction: column;
}

.main-menu.modal>* {
	padding: 0 24px;
}

.main-content {
	padding-left: 10px;
	padding-right: 10px;
}

.modal-backdrop,.modal-wrap {
	position: fixed;
	top: 0;
	right: 0;
	bottom: 0;
	left: 0;
}

.modal-backdrop {
	background-color: var(--backdrop-color);
	opacity: .1;
	z-index: 1040;
}

.modal-wrap {
	z-index: 1041;
	background-color: transparent !important;
	overflow: auto;
}

.modal-open {
	overflow: hidden;
}

.modal {
	border: 1px solid var(--border-color);
	width: 50%;
	padding: 20px 10px;
	margin: 40px auto;
}

@media (max-width: 768px) {
	.modal {
		margin: 0;
		width: 100%;
		min-height: 100%;
	}
}

.row {
	display: -webkit-flex;
	display: flex;
	-webkit-align-items: center;
	align-items: center;
	width: 100%;
	background-color: transparent;
}

.row.top {
	-webkit-align-items: flex-start;
	align-items: flex-start;
}

.row.center {
	-webkit-justify-content: center;
	justify-content: center;
}

.row:after,.row:before {
	display: table;
	content: " ";
}

.row:after {
	clear: both;
}

.row>* {
	display: inline-block;
	-webkit-flex: 0 0 auto;
	flex: 0 0 auto;
	position: relative;
}

.row>.col-expand {
	-webkit-flex: 2 0 auto;
	flex: 2 0 auto;
}

.row>.col-1 {
	width: 25%;
}

.row>.col-2 {
	width: 50%;
}

.row>.col-3 {
	width: 75%;
}

.row>.col-4 {
	width: 100%;
}

.float-left {
	float: left;
}

.float-right {
	float: right;
}

hr {
	border: 0;
	border-bottom: 1px solid var(--border-color);
	margin: 20px 0;
}

.label {
	font-weight: 700;
}

.label.required:after {
	content: "*";
	font-weight: 200;
	margin-left: 3px;
	margin-top: -3px;
	font-size: 18px;
	position: absolute;
	height: 1px;
}

.checkbox.danger>.text,.label.danger,.label.error,.label.required:after {
	color: var(--error-color);
}

.input {
	display: block;
	width: 100%;
	padding: 0 12px;
	border: 0;
	background-color: var(--main-bg-color);
	outline: 0;
	height: 36px;
	border-radius: 0;
	-webkit-appearance: none;
	appearance: none;
	font: inherit;
	color: inherit;
}

.input.error {
	border-color: var(--error-color);
}

.input::-webkit-inner-spin-button,.input::-webkit-outer-spin-button {
	-webkit-appearance: none;
	margin: 0;
}

select.input {
	border-radius: 0;
	background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 140 110"><path stroke="%23555555" fill="none" stroke-width="15" d="m10,10 60,80 60,-80"/></svg>');
	background-size: 18px;
	background-position: right 10px center;
	background-repeat: no-repeat;
	padding-right: 40px;
	-webkit-appearance: none;
	appearance: none;
}

@-moz-document url-prefix() {
	select.input {
		background: 0 0;
	}
}

textarea.input {
	-webkit-overflow-scrolling: touch;
}

.checkbox,.radio {
	display: block;
	width: 100%;
	cursor: pointer;
	position: relative;
	line-height: 16px;
}

.checkbox>*,.radio>* {
	display: inline-block;
	line-height: 16px;
}

.checkbox>input,.radio>input {
	margin-right: .25rem;
	cursor: pointer;
	opacity: 0;
}

.checkbox>input+.inner,.radio>input+.inner {
	width: 1rem;
	height: 1rem;
	border: 1px solid var(--border-color);
	position: absolute;
	left: 0;
	top: 1px;
}

.checkbox>input:checked+.inner:before,.radio>input:checked+.inner:before {
	content: " ";
	display: block;
	border: .1rem solid var(--main-bg-color);
	width: 100%;
	height: 100%;
	background-color: var(--link-color);
}

.checkbox.danger>input:checked+.inner:before {
	background-color: var(--error-color);
}

.radio>input+.inner {
	border-radius: 100%;
}

.radio>input:checked+.inner:before {
	border-radius: 100%;
}

.checkbox>input:focus+.inner,.radio>input:focus+.inner {
	border-style: dotted;
	border-color: var(--text-color);
	z-index: 2;
}

.button {
	cursor: pointer;
	padding: 0 16px;
	margin: 0 6px;
	border: 0;
	outline: 0;
	height: 36px;
	background-color: transparent;
	font: inherit;
	color: inherit;
	font-weight: 600;
	text-transform: uppercase;
	-moz-appearance: none;
	-webkit-appearance: none;
	appearance: none;
}

.button:focus,.button:hover {
	background-color: var(--hover-bg-color);
}

.button.submit,a {
	color: var(--link-color);
}

.button.danger {
	color: var(--error-color);
}

.button[disabled] {
	color: var(--border-color) !important;
	cursor: not-allowed;
	background-color: transparent !important;
}

.input[disabled] {
	cursor: not-allowed;
	border-style: dotted;
}

.progress {
	display: -webkit-flex;
	display: flex;
	width: 100%;
	position: relative;
}

.progress>* {
	display: inline-block;
	height: 100%;
}

.progress>.progress-level {
	-webkit-flex: 0 0 auto;
	flex: 0 0 auto;
	background-color: transparent;
	transition: width 1s;
}

.progress>.progress-overlay {
	-webkit-flex: 2 0 auto;
	flex: 2 0 auto;
	background-color: var(--hover-bg-color);
}

a {
	text-decoration: none;
	outline: 0;
}

a.active,a:focus,a:hover {
	text-decoration: underline;
}

.monospace,code,kbd,pre,samp {
	font-family: "Lucida Console", Monaco, monospace;
}

.table tr>th,.text-left {
	text-align: left;
}

.text-center {
	text-align: center;
}

.text-right {
	text-align: right;
}

.text-gray {
	opacity: .5;
}

.text-delete {
	text-decoration: line-through;
}

.text-italic {
	font-style: italic;
}

.alert-float {
	position: fixed;
	z-index: 2001;
	right: 10px;
	bottom: 10px;
	background: 0 0 !important;
}

.alert-float>.alert {
	margin-bottom: 5px;
	width: 300px;
	padding: 10px;
	border: 1px solid transparent;
}

.alert-float>.alert.alert-info {
	color: var(--info-color);
	background-color: var(--info-bg-color);
	border-color: var(--info-color);
}

.alert-float>.alert.alert-error {
	color: var(--error-color);
	background-color: var(--error-bg-color);
	border-color: var(--error-color);
}

.alert-float>.alert>.alert-text {
	margin: 0;
}

.alert-float>.alert>.alert-title+.alert-text {
	margin-top: 5px;
}

.alert-float>.alert .button {
	margin: 5px 0 0;
}

@media (max-width: 768px) {
	.alert-float {
		left: 10px;
	}

	.alert-float>.alert {
		width: 100%;
	}
}

.table {
	width: 100%;
	border-spacing: 0;
	table-layout: fixed;
	white-space: nowrap;
}

.table tr>* {
	height: 32px;
	padding: 0 5px;
}

.table tr>th {
	position: relative;
}

.table.hover>tbody>tr,.table>thead>tr>th[data-order] {
	cursor: pointer;
	padding-right: 30px;
}

.table>thead>tr>th[data-order]:after,.table>thead>tr>th[data-order]:before {
	content: "";
	display: block;
	position: absolute;
	right: 10px;
	border-color: transparent;
	border-style: solid;
	border-width: 5px;
	width: 0;
	height: 0;
}

.table>thead>tr>th[data-order]:before {
	border-bottom-color: var(--hover-bg-color);
	top: 5px;
}

.table>thead>tr>th[data-order]:after {
	border-top-color: var(--hover-bg-color);
	top: 17px;
}

.table>thead>tr>th[data-order="-1"]:before {
	border-bottom-color: var(--text-color);
}

.table>thead>tr>th[data-order="1"]:after {
	border-top-color: var(--text-color);
}

.table.hover>tbody>tr:hover {
	background-color: var(--hover-bg-color);
}

.table.striped>tbody>tr:nth-child(2n) {
	background-color: var(--border-color);
}

.table td.nowrap,.table th.nowrap {
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}

/* minimal.css */

html.minimal .card .card-status {
	display: none;
}

html.minimal .card .card-image {
	display: none;
}

html.minimal .card .card-name {
	font-weight: 600;
}

html.minimal .card.card-true-2 {
	background-color: var(--success-bright-color);
}

html.minimal .card.card-true-2 .card-name {
	color: var(--success-bright-color-dark);
}

html.minimal .card.card-true-0,
html.minimal .card.card-true-1 {
	background-color: var(--error-bright-color);
}

html.minimal .card.card-true-0 .card-name,
html.minimal .card.card-true-1 .card-name {
	color: var(--error-bright-color-dark);
}

/* dropdown.css */

details.dropdown {
	position: relative;
	width: 34px;
	background: linear-gradient(to right, rgba(255, 255, 255, 0), var(--main-bg-color) 40%, var(--main-bg-color));
}

details.dropdown.wide-menu .menu {
	width: 200px;
}

details.dropdown > summary {
	text-align: right;
	list-style: none;
	cursor: pointer;
}

details.dropdown > summary:focus {
	outline: none;
}

details.dropdown > summary::-webkit-details-marker {
	display: none;
}

details.dropdown[open] > summary::before {
  /* TODO: fix scroll */
	position: fixed;
	content: " ";
	top: 0;
	right: 0;
	bottom: 0;
	left: 0;
	z-index: 50;
	display: block;
	cursor: default;
	background: transparent;
}

details.dropdown > .menu {
	position: absolute;
	display: flex;
	flex-direction: column;
	top: 100%;
	z-index: 100;
	width: 160px;
	padding: 4px 0;
	margin-top: 2px;
	list-style: none;
	background-color: var(--main-bg-color);
	background-clip: padding-box;
	border: 1px solid var(--border-color);
	border-radius: .2rem;
	box-shadow: 0 0 4px 0 var(--border-color);
	pointer-events: none;
  /* top-right */
	left: auto;
	right: 0;
}

details.dropdown > .menu::before {
	position: absolute;
	display: inline-block;
	content: " ";
	border: 8px solid transparent;
	border-bottom-color: var(--border-color);
  /* top-right */
	top: -16px;
	right: 0;
	left: auto;
}

details.dropdown > .menu > hr {
	margin: 4px 0;
}

details.dropdown > .menu > .item {
	padding: 6px 8px;
	pointer-events: auto;
}

details.dropdown > .menu > .item.disable {
	color: var(--border-color);
	cursor: default;
	pointer-events: none;
}

details.dropdown > .menu > .item.disable:hover {
	background-color: var(--main-bg-color);
}

details.dropdown > .menu > .item.small-center {
	font-weight: 200;
	font-size: smaller;
	text-align: center;
	padding: 0;
}

details.dropdown > .menu > .item.selected-item {
	color: var(--main-bg-color);
	background-color: var(--link-color);
}

details.dropdown > .menu > .item.selected-item:hover {
	background-color: var(--link-color);
	color: var(--hover-bg-color);
}

details.dropdown > .menu > .item:hover {
	text-decoration: none;
	background-color: var(--hover-bg-color);
}

/* app.css */

@-webkit-keyframes animIn {
	0% {
		-webkit-transform: translateX(-50px);
		transform: translateX(-50px);
		opacity: 0;
	}

	50% {
		opacity: 1;
	}

	to {
		-webkit-transform: translateX(50px);
		transform: translateX(50px);
		opacity: 0;
	}
}

@keyframes animIn {
	0% {
		-webkit-transform: translateX(-50px);
		transform: translateX(-50px);
		opacity: 0;
	}

	50% {
		opacity: 1;
	}

	to {
		-webkit-transform: translateX(50px);
		transform: translateX(50px);
		opacity: 0;
	}
}

@-webkit-keyframes checkboxSpin {
	0% {
		-webkit-transform: rotate(0);
		opacity: 1;
	}

	50% {
		opacity: 0;
	}

	to {
		-webkit-transform: rotate(360deg);
		opacity: 1;
	}
}

@keyframes checkboxSpin {
	0% {
		transform: rotate(0);
		opacity: 1;
	}

	50% {
		opacity: 0;
	}

	to {
		transform: rotate(360deg);
		opacity: 1;
	}
}

@keyframes card-inactive-bounce {
	0%,to {
		box-shadow: none;
	}

	50% {
		box-shadow: 0 0 5px var(--border-color);
	}
}

@keyframes card-onair-bounce {
	0%,to {
		box-shadow: none;
	}

	50% {
		box-shadow: 0 0 5px #66bb6a;
	}
}

@keyframes card-error-bounce {
	0%,to {
		box-shadow: none;
	}

	50% {
		box-shadow: 0 0 5px #ef5350;
	}
}

@keyframes card-selected-bounce {
	0%,to {
		box-shadow: none;
	}

	50% {
		box-shadow: 0 0 5px #42a5f5;
	}
}

body,html {
	min-height: 100%;
}

.version {
	display: none;
	position: fixed;
	bottom: 2px;
	left: 10px;
	text-transform: uppercase;
	color: #bdbdbd;
	font-size: 10px;
	background: 0 0;
}

.loading {
	position: relative;
	left: 50%;
	height: 5px;
	text-align: center;
	margin: 10px 0;
	width: 0;
}

.loading:after {
	content: "";
	display: table;
	clear: both;
}

.loading .bullet {
	position: absolute;
	padding: 5px;
	border-radius: 50%;
	background: var(--link-color);
	-webkit-animation: animIn 1s ease-in-out 0s infinite;
	animation: animIn 1s ease-in-out 0s infinite;
}

.loading .bullet:nth-child(1) {
	-webkit-animation-delay: 0s;
	animation-delay: 0s;
}

.loading .bullet:nth-child(2) {
	-webkit-animation-delay: .15s;
	animation-delay: .15s;
}

.loading .bullet:nth-child(3) {
	-webkit-animation-delay: .3s;
	animation-delay: .3s;
}

.loading .bullet:nth-child(4) {
	-webkit-animation-delay: .45s;
	animation-delay: .45s;
}

.checkbox.awaiting>.inner {
	-webkit-animation: checkboxSpin 1.2s ease-in-out 0s infinite;
	animation: checkboxSpin 1.2s ease-in-out 0s infinite;
}

.auth {
	max-width: 400px;
	padding: 50px 10px 0;
	margin: 0 auto;
}

.auth>* {
	margin: 0;
}

.auth>.input {
	position: relative;
	height: auto;
	padding: 10px 12px;
	font-size: 16px;
	border: 1px solid var(--border-color);
}

.auth>.input[type="password"] {
	margin-top: -1px;
	margin-bottom: 10px;
}

.auth>.checkbox {
	margin: 10px 0;
}

.auth>.button {
	width: 100%;
	margin: 0;
}

.form-group {
	margin-bottom: 20px;
	position: relative;
	width: 100%;
	max-width: 768px;
	margin-left: auto;
	margin-right: auto;
}

.form-group.group-input {
	display: flex;
	align-items: center;
	border: 1px solid var(--border-color);
}

.form-group.group-input.error {
	border-color: var(--error-color);
	background-color: var(--error-bg-color);
}

.form-group:last-child {
	margin-bottom: 0;
}

.form-group-header {
	margin-bottom: 10px;
	position: relative;
	width: 100%;
	max-width: 768px;
	margin-left: auto;
	margin-right: auto;
	color: var(--text-color);
	text-transform: uppercase;
	font-weight: 600;
	font-size: .75rem;
	letter-spacing: 1px;
	line-height: 32px;
}

.form-group-action {
	float: right;
	text-decoration: none;
	color: #66bb6a;
}

.form-group-action:focus,.form-group-action:hover {
	text-shadow: 0 0 3px var(--border-color);
	z-index: 2;
	text-decoration: none;
}

.form-submit {
	text-align: center;
}

.form-group .label {
	position: absolute;
	top: -.5rem;
	left: .5rem;
	padding: 0 .25rem;
	text-transform: uppercase;
	font-size: .75rem;
	font-weight: 600;
	background-color: var(--main-bg-color);
	color: var(--border-color);
	letter-spacing: 1px;
	z-index: 3;
}

.form-group .label.editable {
	display: flex;
	align-items: center;
	cursor: pointer;
	text-transform: none;
}

.form-group .label.editable:hover::after {
	content: "\270E";
	color: var(--link-color);
	margin-left: 3px;
}

.form-group.group-input textarea {
	border: 0px none;
	padding: 8px 12px;
	width: 100%;
	background-color: var(--main-bg-color);
	font: inherit;
	color: inherit;
	outline: 0;
}

.tab {
	list-style-type: none;
	margin: 0;
	padding: 0;
	overflow: hidden;
	display: -webkit-flex;
	display: flex;
	justify-content: center;
}

.tab>* {
	display: inline-block;
	-webkit-flex: 0 0 auto;
	flex: 0 0 auto;
	padding: 0 10px;
	font-weight: 200;
	line-height: 30px;
	font-size: 16px;
}

.main-content>.form {
	padding: 20px 0;
}

.io-wizard {
	position: relative;
}

.io-wizard input {
	padding-right: 68px;
}

.io-wizard .button-wrap {
	position: absolute;
	right: 2px;
	top: 2px;
	bottom: 2px;
	z-index: 5;
	white-space: nowrap;
}

.icon {
	display: inline-block;
	width: 100%;
	height: 100%;
	background-position: center;
	background-repeat: no-repeat;
}

.button.icon {
	height: 32px;
	width: 32px;
	min-width: 32px;
	border-radius: 50%;
	padding: 0;
	margin: 0 .25rem 0 0;
	overflow: hidden;
	background-size: 28px;
	vertical-align: middle;
}

.button.icon:focus,.button.icon:hover {
	z-index: 2;
}

.button.icon.small {
	height: 24px;
	width: 24px;
	min-width: 24px;
	background-size: 20px;
	margin: 0;
}

select.button.icon {
	color: transparent;
}

select.button.icon>option {
	color: var(--text-color);
	text-transform: none;
}

.icon-settings {
	background-image: url('data:image/svg+xml,<svg fill="%23519ed4" height="32" viewBox="0 0 24 24" width="32" xmlns="http://www.w3.org/2000/svg"><path d="M0 0h24v24H0z" fill="none"/><path d="M19.43 12.98c.04-.32.07-.64.07-.98s-.03-.66-.07-.98l2.11-1.65c.19-.15.24-.42.12-.64l-2-3.46c-.12-.22-.39-.3-.61-.22l-2.49 1c-.52-.4-1.08-.73-1.69-.98l-.38-2.65C14.46 2.18 14.25 2 14 2h-4c-.25 0-.46.18-.49.42l-.38 2.65c-.61.25-1.17.59-1.69.98l-2.49-1c-.23-.09-.49 0-.61.22l-2 3.46c-.13.22-.07.49.12.64l2.11 1.65c-.04.32-.07.65-.07.98s.03.66.07.98l-2.11 1.65c-.19.15-.24.42-.12.64l2 3.46c.12.22.39.3.61.22l2.49-1c.52.4 1.08.73 1.69.98l.38 2.65c.03.24.24.42.49.42h4c.25 0 .46-.18.49-.42l.38-2.65c.61-.25 1.17-.59 1.69-.98l2.49 1c.23.09.49 0 .61-.22l2-3.46c.12-.22.07-.49-.12-.64l-2.11-1.65zM12 15.5c-1.93 0-3.5-1.57-3.5-3.5s1.57-3.5 3.5-3.5 3.5 1.57 3.5 3.5-1.57 3.5-3.5 3.5z"/></svg>');
}

.icon-close {
	background-image: url('data:image/svg+xml,<svg fill="%23519ed4" height="32" viewBox="0 0 24 24" width="32" xmlns="http://www.w3.org/2000/svg"><path d="M0 0h24v24H0z" fill="none"/><path d="M14.59 8L12 10.59 9.41 8 8 9.41 10.59 12 8 14.59 9.41 16 12 13.41 14.59 16 16 14.59 13.41 12 16 9.41 14.59 8zM12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.53 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z"/></svg>');
}

.icon-move {
	background-image: url('data:image/svg+xml,<svg fill="%23519ed4" height="32" viewBox="0 0 24 24" width="32" xmlns="http://www.w3.org/2000/svg"><path d="M16 17.01V10h-2v7.01h-3L15 21l4-3.99h-3zM9 3L5 6.99h3V14h2V6.99h3L9 3z"/><path d="M0 0h24v24H0z" fill="none"/></svg>');
}

.icon-more {
	background-image: url('data:image/svg+xml,<svg fill="%23519ed4" height="32" viewBox="0 0 24 24" width="32" xmlns="http://www.w3.org/2000/svg"><path d="M0 0h24v24H0z" fill="none"/><path d="M6 10c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm12 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm-6 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"/></svg>');
}

.icon-add {
	background-image: url('data:image/svg+xml,<svg fill="%23519ed4" height="32" viewBox="0 0 24 24" width="32" xmlns="http://www.w3.org/2000/svg"><path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/><path d="M0 0h24v24H0z" fill="none"/></svg>');
}

.icon-info {
	background-image: url('data:image/svg+xml,<svg fill="%23519ed4" width="32" height="32" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path fill="none" d="M0 0h24v24H0V0z"/><path d="M11 7h2v2h-2zm0 4h2v6h-2zm1-9C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z"/></svg>');
}

.help {
	cursor: help;
}

.settings-edit {
	display: -webkit-flex;
	display: flex;
	-webkit-flex-direction: column;
	flex-direction: column;
	position: absolute;
	top: 30px;
	right: 0;
	bottom: 0;
	left: 0;
}

.settings-edit .input {
	white-space: pre-wrap;
	word-wrap: break-word;
	outline: 0;
	resize: none;
	border: 0;
	padding: 10px;
	-webkit-flex: 1 1 auto;
	flex: 1 1 auto;
}

.settings-edit .input:focus {
	box-shadow: none;
}

.card-stack {
	text-align: center;
	margin: 5px 0;
	display: grid;
	grid-column-gap: 1px;
	grid-row-gap: 1px;
	justify-content: center;
	grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
	align-items: start;
}

.card-stack[data-header]:before {
	content: attr(data-header);
	color: var(--border-color);
	text-transform: uppercase;
	font-weight: 600;
	font-size: 12px;
	letter-spacing: 1px;
	text-align: center;
	grid-column-start: 1;
	grid-column-end: -1;
	margin: .5em 0;
}

.card {
	border: 1px solid var(--border-color);
	text-align: left;
	cursor: pointer;
	display: inline-block;
	vertical-align: top;
	position: relative;
	color: inherit;
}

.card:focus,.card:hover {
	text-decoration: none;
	outline: 0;
}

.card .card-name,.card .card-status {
	white-space: nowrap;
	overflow: hidden;
	margin: 0 3px;
}

.card .card-name {
	line-height: 24px;
	font-size: 16px;
	font-weight: 200;
}

.card .card-action {
	position: absolute;
	top: 0;
	right: 0;
}

.card .card-status {
	line-height: 18px;
	font-size: 14px;
}

.card .card-footer {
	margin-top: 2px;
	border-top: 1px solid var(--border-color);
}

.card .card-status .text {
	display: block;
}

.card .card-status .text.onair {
	color: #66bb6a;
}

.card .card-status .text.cc,.card .card-status .text.error,.card .card-status .text.scrambled {
	color: #ef5350;
}

.card .card-image {
	height: 100px;
	background-position: center;
	background-repeat: no-repeat;
	background-size: cover;
	margin: 0 3px;
	display: none;
}

@media (max-width: 768px) {
	.card-stack {
		grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
	}
}

.card.card-false-0,
.card.card-true-3 {
	animation: card-inactive-bounce 1s;
}

.card.card-false-0 {
	border-style: dotted;
}

.card .card-status .text,
.card.card-false-0 .card-name {
	color: var(--border-color);
}

.card.card-true-2 {
	border-color: #66bb6a;
	animation: card-onair-bounce 1s;
}

.card.card-true-0,.card.card-true-1 {
	border-color: #ef5350;
	animation: card-error-bounce 1s;
}

.card.selected,.card:focus {
	border-color: #42a5f5;
	animation: card-selected-bounce 1s;
}

.card.selected:hover {
	border-color: #1565c0;
}

.card.selected:before {
	content: " ";
	float: right;
	border-top: 10px solid #42a5f5;
	border-left: 10px solid transparent;
}

.card.selected:hover:before {
	border-top-color: #1565c0;
}

.card.updated:before {
	content: "\25cf";
	color: #42a5f5;
	font-size: 24px;
	position: absolute;
	right: 5px;
	top: -5px;
}

.card.stream-mpts .card-status .text[data-name]:after {
	content: attr(data-name);
	padding-left: 5px;
}

.card-hide-disabled .card.card-false-0,.card-hide-inactive .card.card-true-3,.card-hide-wo-error .card.card-true-2 {
	display: none;
}

.signal-level {
	background: url('data:image/svg+xml;utf8,<svg width="100%" height="16" xmlns="http://www.w3.org/2000/svg"><defs><linearGradient id="g1"><stop stop-color="%23F44336" offset="0%"/><stop stop-color="%23FFFF00" offset="25%"/><stop stop-color="%2300E676" offset="75%"/><stop stop-color="%2300E676" offset="100%"/></linearGradient></defs><rect fill="url(%23g1)" x="0" y="0" width="100%" height="100%"/></svg>');
	background-repeat: no-repeat;
	height: 16px;
}

.dvb-scan .dvb-status {
	margin-top: 5px;
}

.dvb-status {
	width: auto;
}

.dvb-status>:nth-child(1) {
	width: 10px;
}

.dvb-status>:nth-child(2) {
	width: auto;
}

.dvb-status>:nth-child(3) {
	width: 30px;
	text-align: right;
}

.info-status,.satip-status {
	text-align: left;
}

.info-status>*,.satip-status>* {
	white-space: pre;
	padding-right: 10px;
}

.info-status>:last-child,.satip-status>:last-child {
	float: right;
	padding-right: 0;
}

.er,.info-status>.er,.satip-status>.er {
	color: #ef5350;
}

.info-status>.ok,.log .log-item.log-0,.ok,.satip-status>.ok {
	color: #66bb6a;
}

.satip-status>:nth-child(1):before {
	content: "CONNECT";
}

@media (min-width: 768px) {
	.info-status>:nth-child(1):before {
		content: "SIGNAL";
	}

	.info-status>:nth-child(2):before {
		content: "CARRIER";
	}

	.info-status>:nth-child(3):before {
		content: "FEC";
	}

	.info-status>:nth-child(4):before {
		content: "SYNC";
	}

	.info-status>:nth-child(5):before {
		content: "LOCK";
	}
}

@media (max-width: 768px) {
	.info-status>:nth-child(1),.info-status>:nth-child(2),.info-status>:nth-child(3),.info-status>:nth-child(4) {
		padding-right: 0;
	}

	.info-status>:nth-child(1):before {
		content: "S";
	}

	.info-status>:nth-child(2):before {
		content: "C";
	}

	.info-status>:nth-child(3):before {
		content: "V";
	}

	.info-status>:nth-child(4):before {
		content: "Y";
	}

	.info-status>:nth-child(5):before {
		content: "L";
	}
}

.table .action {
	text-align: right;
	width: 0;
	padding: 0;
}

.modal.help {
	padding: 20px 0;
	margin: 0;
	width: auto;
	position: fixed;
	top: 40px;
	right: 40px;
	bottom: 40px;
	left: 40px;
	display: flex;
	flex-direction: column;
}

.modal.help>iframe {
	border: 0;
	flex: 1;
}

@media (max-width: 768px) {
	.modal.help {
		margin: 0;
		top: 0;
		right: 0;
		bottom: 0;
		left: 0;
	}
}

.log {
	margin: 0;
	padding: 5px 0 40px;
}

.log .log-item {
	white-space: nowrap;
	margin: 2px 0;
}

.log .log-item.log-1 {
	color: #ef5350;
}

.log .log-item.log-2 {
	color: #ffca28;
}

.log .log-item.log-3 {
	color: #777;
}

.log .log-item>* {
	display: inline-block;
	white-space: pre;
}

.log .log-item>.log-time {
	margin-right: 5px;
}

.log .log-item>.log-text {
	margin-left: 5px;
}

.log-footer {
	background-color: inherit;
	padding-left: 10px;
	position: fixed;
	right: 0;
	bottom: 0;
	left: 0;
}

.log-footer .button {
	margin: 0;
}

.log-footer .checkbox {
	display: inline-block;
	width: auto;
	margin-right: 10px;
}

.analyze-ui .psi {
	padding-left: 1rem;
}

.card-stack.card-order-status .card-adapter.card-true-0 {
	order: 0;
}

.card-stack.card-order-status .card-stream.card-true-0 {
	order: 3;
}

.card-stack.card-order-status .card-stream.card-true-2 {
	order: 4;
}

.card {
	order: 5;
}

.card.card-adapter {
	order: 1;
}

.card.card-adapter.card-false-0 {
	order: 2;
}

.card.card-stream.card-false-0 {
	order: 10;
}

    </style>
</head>
<body>
<script>
/* Astra: Web Interface */
/* https://cesbo.com/astra/ */
/* Copyright (C) 2012-2023, Cesbo OU <info@cesbo.com> */

/* pony.js */

(function() {
"use strict";
window.$ = function(x) {
	if(typeof x === "string") {
		return document.querySelectorAll(x);
	} else if(typeof x === "function") {
		document.addEventListener("DOMContentLoaded", function w() {
			document.removeEventListener("DOMContentLoaded", w, false);
			x();
		});
	}
};
String.prototype.toUpperCaseFirst = function() {
	return this.charAt(0).toUpperCase() + this.slice(1);
};
if(!String.prototype.format) {
	String.prototype.format = function() {
		var args = arguments;
		return this.replace(/{(\d+)}/g, function(match, number) {
			return typeof args[number] != "undefined" ? args[number] : match;
		});
	};
}
if(!String.prototype.trim) {
	String.prototype.trim = function() {
		return this.replace(/^\s+|\s+$/gm, "");
	};
}
Array.prototype.find = function(fn) {
	for(var i = 0, l = this.length; i < l; ++i) {
		var x = this[i];
		if(fn(x)) return x;
	}
	return undefined;
};
Array.prototype.move = function(src, dst) {
	var e = this.splice(src, 1)[0];
	this.splice(dst, 0, e);
};
Array.prototype.insertSorted = function(item, fn) {
	var l = 0,
		h = this.length,
		m;
	while(l < h) {
		m = (l + h) >>> 1;
		if(fn(this[m], item) < 0) l = m + 1;
		else h = m;
	}
	this.splice(l, 0, item);
};
Element.prototype.remove = function() {
	if(this.eventBind) {
		for(var event in this.eventBind) {
			var eb = this.eventBind[event];
			this.removeEventListener(event, eb.fn);
			delete this.eventBind[event];
		}
		delete this.eventBind;
	}
	this.parentNode.removeChild(this);
};
Element.prototype.empty = function() {
	while(this.firstChild) this.firstChild.remove();
	return this;
};
Element.prototype.addClass = function() {
	var clist = !!this.className ? this.className.split(/ +/) : [];
	for(var i = 0; i < arguments.length; i++) {
		var n = arguments[i];
		if(!n) continue;
		n = n.split(/ +/);
		while(n.length) {
			var c = n.shift();
			if(clist.indexOf(c) == -1) clist.push(c);
		}
	}
	this.className = clist.join(" ");
	return this;
};
Element.prototype.removeClass = function() {
	var clist = !!this.className ? this.className.split(/ +/) : [];
	for(var i = 0; i < arguments.length; i++) {
		var n = arguments[i];
		if(!n) continue;
		n = n.split(/ +/);
		while(n.length) {
			var c = n.shift();
			var j = clist.indexOf(c);
			if(j != -1) clist.splice(j, 1);
		}
	}
	this.className = clist.join(" ");
	return this;
};
Element.prototype.hasClass = function(c) {
	var clist = this.className.split(/ +/);
	return clist.indexOf(c) != -1;
};
Element.prototype.addAttr = function(key, value) {
	if(value == undefined) value = "";
	this.setAttribute(key, value);
	return this;
};
Element.prototype.removeAttr = function(key) {
	this.removeAttribute(key);
	return this;
};
Element.prototype.setValue = function(value) {
	if(value) this.addAttr("value", value);
	else this.removeAttr("value");
	return this;
};
Element.prototype.setText = function(text) {
	this.textContent = text;
	return this;
};
Element.prototype.setHtml = function(html) {
	this.innerHTML = html;
	return this;
};
Element.prototype.setReadonly = function(value) {
	return this[!!value ? "addAttr" : "removeAttr"]("readonly");
};
Element.prototype.setDisabled = function(value) {
	return this[!!value ? "addAttr" : "removeAttr"]("disabled");
};
Element.prototype.setRequired = function(value) {
	return this[!!value ? "addAttr" : "removeAttr"]("required");
};
Element.prototype.setError = function(value) {
	return this[!!value ? "addClass" : "removeClass"]("error");
};
Element.prototype.setStyle = function(key, value) {
	var x = key.split("-");
	key = x.shift();
	while(x.length) key += x.shift().toUpperCaseFirst();
	this.style[key] = value;
	return this;
};
Element.prototype.addValidator = function(fn) {
	if(this.$validate == undefined) this.$validate = [];
	this.$validate.push(fn);
	return this;
};
Element.prototype.addChild = function() {
	for(var i = 0; i < arguments.length; ++i) {
		var child = arguments[i];
		if(child) {
			if(child.nodeName == undefined) child = document.createTextNode(child);
			this.appendChild(child);
		}
	}
	return this;
};
Element.prototype.insertChild = function(child, before) {
	if(child) {
		if(child.nodeName == undefined) child = document.createTextNode(child);
		this.insertBefore(child, before || this.firstChild);
	}
	return this;
};
Element.prototype.insertSorted = function(child, fn) {
	var l = 0,
		h = this.childNodes.length,
		m;
	while(l < h) {
		m = (l + h) >>> 1;
		if(fn(this.childNodes[m], child) < 0) l = m + 1;
		else h = m;
	}
	if(l == this.childNodes.length) this.addChild(child);
	else this.insertChild(child, this.childNodes[l]);
	return this;
};
Element.prototype.dataBind = function(key) {
	if(key) this.addAttr("data-bind", key);
	return this;
};
var eventOn = function(event, fn) {
	if(!this.eventBind) this.eventBind = {};
	var eb = this.eventBind[event];
	if(!eb) {
		this.eventBind[event] = eb = {
			list: [],
			fn: function() {
				for(var i = 0; i < eb.list.length; i++) eb.list[i].apply(this, arguments);
			},
		};
		this.addEventListener(event, eb.fn);
	}
	eb.list.push(fn);
	return this;
};
var eventOff = function(event, fn) {
	var eb = !!this.eventBind ? this.eventBind[event] : null;
	if(eb) {
		if(!!fn) {
			var x = eb.list.indexOf(fn);
			if(x != -1) eb.list.splice(x, 1);
			if(!eb.list.length) fn = undefined;
		}
		if(!fn) {
			this.removeEventListener(event, eb.fn);
			delete this.eventBind[event];
		}
	}
	return this;
};
var eventEmit = function(event) {
	var eb = !!this.eventBind ? this.eventBind[event] : null;
	if(eb) {
		eb.fn.apply(this, Array.prototype.slice.call(arguments, 1));
	}
	return this;
};
Element.prototype.on = eventOn;
Element.prototype.off = eventOff;
Element.prototype.emit = eventEmit;
window.on = eventOn;
window.off = eventOff;
window.emit = eventEmit;
document.on = eventOn;
document.off = eventOff;
document.emit = eventEmit;
$.html = document.querySelector("html");
$.head = document.querySelector("head");
$.nop = function() {};
$.element = function(t) {
	return document.createElement(t || "div");
};
$.body = $.element();
$.base = document.querySelector("body");
$.base.addChild($.body);
$.element.button = function(text) {
	return $.element("button")
		.addAttr("type", "button")
		.addClass("button")
		.setText(text || "");
};
$.element.a = function(href, text) {
	return $.element("a")
		.addAttr("href", href)
		.setText(text || "");
};
$.element.input = function(placeholder, type) {
	return $.element("input")
		.addAttr("type", type || "text")
		.addClass("input")
		.addAttr("placeholder", placeholder);
};
$.element.select = function(items) {
	var x = $.element("select").addClass("input");
	var makeItems = function(p, x) {
		for(var i = 0; i < x.length; i++) {
			var e,
				o = x[i];
			if(o.hide) continue;
			if(o.group) {
				if(!o.items.length) continue;
				e = $.element("optgroup").addAttr("label", o.group);
				makeItems(e, o.items);
			} else {
				e = $.element("option")
					.addAttr("value", o.value)
					.setText(o.label || o.value);
			}
			if(o.disabled) e.setDisabled(true);
			p.addChild(e);
		}
	};
	makeItems(x, items);
	return x;
};
$.element.checkbox = function(label) {
	var x = $.element("input").addAttr("type", "checkbox");
	var z = $.element("label")
		.addClass("checkbox")
		.addChild(x)
		.addChild($.element("span").addClass("inner"))
		.addChild(
			$.element("span")
				.addClass("text")
				.setHtml(label || "")
		);
	z.checkbox = x;
	z.dataBind = function(key) {
		x.dataBind(key);
	};
	return z;
};
$.element.script = function(src) {
	return $.element("script").addAttr("type", "text/javascript").addAttr("src", src);
};
$.isArray = function(v) {
	return !!v && v.length != undefined && (v.constructor == Array || v.constructor == NodeList);
};
$.isObject = function(v) {
	return v === Object(v) && $.isArray(v) == false;
};
$.isObjectEmpty = function(v) {
	for(var k in v) {
		if(v.hasOwnProperty(k)) return false;
	}
	return true;
};
$.clone = function(v) {
	if($.isArray(v)) return v.slice();
	if($.isObject(v)) return JSON.parse(JSON.stringify(v));
	return v;
};
$.forEach = function(v, fn) {
	if(!v) {
	} else if($.isArray(v)) {
		for(var k = 0, l = v.length; k < l; k++) {
			var x = fn(v[k], k);
			if(x != undefined) return x;
		}
	} else if($.isObject(v)) {
		for(var k in v) {
			var x = fn(v[k], k);
			if(x != undefined) return x;
		}
	}
};
$.http = function(config, onLoad, onError) {
	var u = config.url,
		m = config.method || "GET";
	if(u.match(/^\/\//)) u = location.protocol + u;
	var x = new XMLHttpRequest();
	if(!u.match(/^[a-z]+:\/\//)) {
		x.open(m, u);
	} else if("withCredentials" in x) {
		x.open(m, u, true);
	} else if("XDomainRequest" in window) {
		x = new XDomainRequest();
		x.open(m, u);
	} else {
		throw new Error("CORS not supported");
	}
	$.forEach(config.headers, function(v, k) {
		x.setRequestHeader(k, v);
	});
	var response = function() {
		var fn = x.status == 200 ? onLoad : onError;
		if(fn) fn({
			text: x.responseText,
			status: x.status,
			statusText: x.statusText
		});
	};
	x.addEventListener("load", response);
	x.addEventListener("error", response);
	x.send(config.data);
};
function Cookie() {
	var data = {};
	$.forEach(document.cookie.split(/; +/), function(kv) {
		if(kv != "") {
			kv = kv.split("=");
			data[kv[0]] = decodeURIComponent(kv[1]);
		}
	});
	this.get = function(key) {
		return data[key] || undefined;
	};
	this.set = function(key, value, expires) {
		var x = key + "=";
		if(value != undefined) {
			data[key] = value;
			x += encodeURIComponent(value);
		} else {
			delete data[key];
			expires = -1;
		}
		if(expires != undefined) x += "; expires=" + new Date(expires == -1 ? 946684801e3 : Date.now() + Math.round(expires * 864e5)).toUTCString();
		document.cookie = x;
	};
	this.getObject = function(key) {
		var x = this.get(key);
		if(x) x = JSON.parse(x);
		return x;
	};
	this.setObject = function(key, value) {
		if(value) value = JSON.stringify(value);
		this.set(key, value);
	};
}
$.cookie = new Cookie();
var msgFloat = null;
$.msg = function(config) {
	if(!msgFloat) {
		msgFloat = $.element("div").addClass("alert-float");
		$.base.addChild(msgFloat);
	}
	var c,
		t,
		x = $.element("div").addClass("alert alert-" + (config.type || "info")),
		d = config.delay || 3;
	if(config.title) x.addChild($.element("strong").addClass("alert-title").setText(config.title));
	if(config.text) x.addChild((c = $.element("p").addClass("alert-text").setText(config.text.format(d))));
	x.button = function(text, fn) {
		x.addChild(
			$.element()
				.addClass("row")
				.addChild(
					$.element
						.button(text)
						.addClass("col-4")
						.on("click", function(event) {
							fn.call(x, event);
						})
				)
		);
		return x;
	};
	x.remove = function() {
		if(t) clearInterval(t);
		Element.prototype.remove.call(this);
		x.emit("remove");
	};
	if(d > 0) {
		t = setInterval(function() {
			d--;
			if(!d) x.remove();
			else if(c) c.setText(config.text.format(d));
		}, 1e3);
	}
	msgFloat.addChild(x);
	return x;
};
$.err = function(config) {
	config.type = "error";
	return $.msg(config);
};
var modalStack = [];
$.modal = function() {
	var onEsc = function(event) {
		if(event.keyCode == 27) modalStack[modalStack.length - 1].firstChild.remove();
	};
	if(!modalStack.length) {
		var backdrop = $.element("div").addClass("modal-backdrop");
		$.base.addChild(backdrop);
		$.base.addClass("modal-open");
		modalStack.push(backdrop);
		document.on("keyup", onEsc);
	}
	var m = $.element("div")
		.addClass("modal")
		.on("click", function(event) {
			event.stopPropagation();
		});
	var w = $.element("div")
		.addClass("modal-wrap")
		.addChild(m);
	if(modalStack.length > 1) modalStack[modalStack.length - 1].addClass("hide");
	modalStack.push(w);
	$.base.addChild(w);
	var remove = function(e) {
		modalStack.splice(modalStack.length - 1, 1);
		var n = modalStack[modalStack.length - 1];
		if(modalStack.length > 1) {
			n.removeClass("hide");
		} else {
			$.base.removeClass("modal-open");
			n.remove();
			modalStack.splice(0, 1);
			document.off("keyup", onEsc);
		}
		m.parentNode.remove();
		m.emit(e);
	};
	m.set = function(k, v) {
		if(v == undefined) delete m[k];
		else m[k] = v;
		return m;
	};
	m.remove = function() {
		remove("remove");
	};
	m.submit = function() {
		remove("submit");
	};
	return m;
};
Element.prototype.bindScope = function(render, data) {
	var self = this,
		args = Array.prototype.slice.call(arguments, 2);
	if(!$.isObject(data)) {
		console.warn("bindScope() argument #2 object expected");
		data = {};
	}
	if(self.scope) self.scope.destroy();
	var dataErrors = {};
	var dataValidate = function() {
		var e = this,
			r = false;
		$.forEach(e.$validate, function(fn) {
			if(!fn.call(e, e.value)) r = true;
		});
		if(e.$error != r) {
			e.setError(r);
			e.$error = r;
			if(r) dataErrors[e.dataset.bind] = true;
			else delete dataErrors[e.dataset.bind];
		}
	};
	var setDataBind = function(e, t) {
		var key = e.dataset.bind;
		if(!self.scope.map[key]) self.scope.map[key] = [];
		self.scope.map[key].push(e);
		e.addAttr("name", e.dataset.bind);
		switch(t) {
			case "text":
			case "password":
			case "textarea":
			case "number":
				e.bindEvent = "input";
				e.bindSetValue = function(val) {
					this.value = val !== undefined ? val : "";
				};
				e.bindGetValue = function() {
					return this.value !== "" ? this.value : undefined;
				};
				break;
			case "hidden":
				e.bindSetValue = function(val) {
					this.value = val !== undefined ? val : "";
				};
				break;
			case "select":
				e.bindEvent = "change";
				e.bindSetValue = function(val) {
					this.value = val !== undefined ? val : "";
				};
				e.bindGetValue = function() {
					return this.value !== "" ? this.value : undefined;
				};
				break;
			case "checkbox":
				var x = function(v) {
					var s = v.toString();
					if(!e.dataset.hasOwnProperty(s)) return v;
					v = e.dataset[s];
					switch(v) {
						case "true":
							return true;
						case "false":
							return false;
						case "undefined":
							return undefined;
						default:
							return v;
					}
				};
				e.value_map = {};
				e.value_map[true] = x(true);
				e.value_map[false] = x(false);
				e.bindEvent = "change";
				e.bindSetValue = function(val) {
					this.checked = this.value_map[true] === val;
				};
				e.bindGetValue = function() {
					return this.value_map[this.checked];
				};
				break;
			case "radio":
				e.bindEvent = "change";
				e.bindSetValue = function(val) {
					this.checked = this.value === val;
				};
				e.bindGetValue = function() {
					return this.value;
				};
				break;
		}
		e.bindSetValue(self.scope.get(key));
		if(e.bindEvent) {
			e.on(e.bindEvent, function() {
				var x = this.bindSetValue;
				this.bindSetValue = $.nop;
				self.scope.set(this.dataset.bind, this.bindGetValue());
				this.bindSetValue = x;
				if(this.$validate) dataValidate.call(this);
			});
			var x = e.eventBind[e.bindEvent].list;
			if(x.length > 1) x.move(x.length - 1, 0);
		}
		if(e.$validate) dataValidate.call(e);
	};
	var setDataValue = function(e) {
		var key = e.dataset.bind;
		if(!self.scope.map[key]) self.scope.map[key] = [];
		self.scope.map[key].push(e);
		e.scope = self;
		e.bindSetValue = function(val) {
			this.textContent = val !== undefined ? val : "";
		};
		e.bindSetValue(self.scope.get(key));
	};
	var bind = function() {
		render.apply(self, args);
		var el = self.querySelectorAll("*[data-bind]");
		for(var i = 0; i < el.length; ++i) {
			var e = el[i];
			switch(e.tagName) {
				case "INPUT":
					setDataBind(e, e.type);
					break;
				case "TEXTAREA":
					setDataBind(e, "textarea");
					break;
				case "SELECT":
					setDataBind(e, "select");
					break;
				default:
					setDataValue(e);
					break;
			}
		}
	};
	self.scope = {};
	var scopeClear = function() {
		self.scope.map = {};
		self.scope.events = {};
		self.empty();
		dataErrors = {};
	};
	self.scope.reset = function(scopeData) {
		if(scopeData) data = scopeData;
		scopeClear();
		bind();
		self.emit("ready").off("ready");
	};
	self.scope.destroy = function() {
		self.emit("destroy").off("destroy");
		scopeClear();
		delete self.scope;
	};
	self.scope.set = function(key, value) {
		var dst = data;
		var k = key.match(/(\\\.|[^\.])+/g);
		while(k.length > 1) {
			var sk = k.shift().replace(/\\\./g, ".");
			if(dst[sk] == undefined) dst[sk] = {};
			dst = dst[sk];
		}
		k = k[0].replace(/\\\./g, ".");
		if(value != undefined) {
			dst[k] = value;
		} else {
			value = "";
			delete dst[k];
		}
		$.forEach(self.scope.map[key], function(e) {
			e.bindSetValue(value);
			if(e.dataset.validate) validateAction.call(e);
		});
	};
	self.scope.get = function(key) {
		var src = data;
		var k = key.match(/(\\\.|[^\.])+/g);
		while(k.length > 1) {
			var sk = k.shift().replace(/\\\./g, ".");
			src = src[sk];
			if(src == undefined) return undefined;
		}
		k = k[0].replace(/\\\./g, ".");
		return src[k];
	};
	self.scope.validate = function() {
		if(!$.isObjectEmpty(dataErrors)) {
			console.log(dataErrors);
			return false;
		} else {
			return true;
		}
	};
	self.scope.serialize = function() {
		var x = $.clone(data);
		$.forEach(x, function(v, k) {
			if(k.charAt(0) == "$") delete x[k];
		});
		return x;
	};
	setTimeout(function() {
		self.scope.reset();
	});
	return self;
};
Element.prototype.dataOrder = function(fn, def) {
	this.addAttr("data-order", def ? 1 : 0);
	this.$order = fn;
	return this;
};
$.tableInit = function(table) {
	var i,
		thead = table.querySelector("thead").firstChild,
		tbody = table.querySelector("tbody");
	table.$orderId = -1;
	var reorder = function() {
		var x = thead.cells[table.$orderId];
		var a = new Array();
		for(i = 0; i < tbody.rows.length; ++i) a[i] = tbody.rows[i];
		a.sort(function(a, b) {
			return x.$order(a.cells[table.$orderId], b.cells[table.$orderId]) * x.dataset.order;
		});
		while(a.length) tbody.appendChild(a.shift());
	};
	for(i = 0; i < thead.cells.length; ++i) {
		var e = thead.cells[i];
		if(e.dataset.order != undefined) {
			if(table.$orderId == -1 || e.dataset.order != 0) table.$orderId = i;
			e.$orderId = i;
			e.on("click", function() {
				if(table.$orderId == this.$orderId) {
					thead.cells[table.$orderId].dataset.order *= -1;
				} else {
					thead.cells[table.$orderId].dataset.order = 0;
					table.$orderId = this.$orderId;
					thead.cells[table.$orderId].dataset.order = 1;
				}
				reorder();
			});
		}
	}
	reorder();
};
$.tableSortInsert = function(table, row) {
	var thead = table.querySelector("thead").firstChild;
	var tbody = table.querySelector("tbody");
	var x = thead.cells[table.$orderId];
	var r = row.cells[table.$orderId];
	var l = 0,
		m = tbody.rows.length;
	while(l < m) {
		var mid = (l + m) >>> 1;
		if(x.$order(tbody.rows[mid].cells[table.$orderId], r) * x.dataset.order < 0) l = mid + 1;
		else m = mid;
	}
	if(l == tbody.rows.length) tbody.appendChild(row);
	else tbody.insertBefore(row, tbody.rows[l]);
};
$.tableFilter = function(table, filter) {
	for(var i = 0; i < table.rows.length; ++i) {
		var row = table.rows[i];
		row.removeClass("hide");
		if(filter) {
			var hide = true;
			for(var j = 0; j < row.cells.length; ++j) {
				var cell = row.cells[j].innerHTML;
				if(cell.toLowerCase().indexOf(filter) != -1) {
					hide = false;
					break;
				}
			}
			if(hide) row.addClass("hide");
		}
	}
};
var utf8 = {
	encode: function(string) {
		string = string.replace(/\r\n/g, "\n");
		var utftext = "";
		for(var i = 0; i < string.length; i++) {
			var c = string.charCodeAt(i);
			if(c < 128) {
				utftext += String.fromCharCode(c);
			} else if(c > 127 && c < 2048) {
				utftext += String.fromCharCode((c >> 6) | 192);
				utftext += String.fromCharCode((c & 63) | 128);
			} else {
				utftext += String.fromCharCode((c >> 12) | 224);
				utftext += String.fromCharCode(((c >> 6) & 63) | 128);
				utftext += String.fromCharCode((c & 63) | 128);
			}
		}
		return utftext;
	},
	decode: function(utftext) {
		var string = "";
		for(var i = 0; i < utftext.length; ) {
			var c = utftext.charCodeAt(i);
			if(c < 128) {
				string += String.fromCharCode(c);
				i++;
			} else if(c > 191 && c < 224) {
				string += String.fromCharCode(((c & 31) << 6) | (utftext.charCodeAt(i + 1) & 63));
				i += 2;
			} else {
				string += String.fromCharCode(((c & 15) << 12) | ((utftext.charCodeAt(i + 1) & 63) << 6) | (utftext.charCodeAt(i + 2) & 63));
				i += 3;
			}
		}
		return string;
	},
};
$.base64Decode = function(text) {
	return utf8.decode(atob(text));
};
$.base64Encode = function(text) {
	return btoa(utf8.encode(text));
};
/* Dropdown menu */
$.dropdown = function(button, items) {
	const summary = $.element("summary").addChild(button).on("click", (event) => {
		event.stopPropagation();
	});
	const menu = $.element().addClass("menu");
	const node = $.element("details").addClass("dropdown").addChild(summary, menu);
	for(const i of items) {
		if(i.label == "---") {
			menu.addChild($.element("hr"));
			continue;
		}
		const item = $.element("a").addClass("item").addAttr("href", (i.href != undefined) ? i.href : "").setText(i.label);
		menu.addChild(item);
		if(i.hide) {
			item.addClass("hide");
			continue;
		}
		if(i.disable) {
			item.addClass("disable");
			continue;
		}
		if(i.style) {
			item.addClass(i.style);
		}
		if(i.click) {
			item.on("click", ev => {
				ev.stopPropagation();
				ev.preventDefault();
				node.open = false;
				i.click();
			});
		}
	}
	return node;
};
})();

/* vue.min.js */

!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e=e||self).Vue=t()}(this,function(){"use strict";var e=Object.freeze({});function t(e){return null==e}function n(e){return null!=e}function r(e){return!0===e}function i(e){return"string"==typeof e||"number"==typeof e||"symbol"==typeof e||"boolean"==typeof e}function o(e){return null!==e&&"object"==typeof e}var a=Object.prototype.toString;function s(e){return"[object Object]"===a.call(e)}function c(e){var t=parseFloat(String(e));return t>=0&&Math.floor(t)===t&&isFinite(e)}function u(e){return n(e)&&"function"==typeof e.then&&"function"==typeof e.catch}function l(e){return null==e?"":Array.isArray(e)||s(e)&&e.toString===a?JSON.stringify(e,null,2):String(e)}function f(e){var t=parseFloat(e);return isNaN(t)?e:t}function p(e,t){for(var n=Object.create(null),r=e.split(","),i=0;i<r.length;i++)n[r[i]]=!0;return t?function(e){return n[e.toLowerCase()]}:function(e){return n[e]}}var d=p("slot,component",!0),v=p("key,ref,slot,slot-scope,is");function h(e,t){if(e.length){var n=e.indexOf(t);if(n>-1)return e.splice(n,1)}}var m=Object.prototype.hasOwnProperty;function y(e,t){return m.call(e,t)}function g(e){var t=Object.create(null);return function(n){return t[n]||(t[n]=e(n))}}var _=/-(\w)/g,b=g(function(e){return e.replace(_,function(e,t){return t?t.toUpperCase():""})}),$=g(function(e){return e.charAt(0).toUpperCase()+e.slice(1)}),w=/\B([A-Z])/g,C=g(function(e){return e.replace(w,"-$1").toLowerCase()});var x=Function.prototype.bind?function(e,t){return e.bind(t)}:function(e,t){function n(n){var r=arguments.length;return r?r>1?e.apply(t,arguments):e.call(t,n):e.call(t)}return n._length=e.length,n};function k(e,t){t=t||0;for(var n=e.length-t,r=new Array(n);n--;)r[n]=e[n+t];return r}function A(e,t){for(var n in t)e[n]=t[n];return e}function O(e){for(var t={},n=0;n<e.length;n++)e[n]&&A(t,e[n]);return t}function S(e,t,n){}var T=function(e,t,n){return!1},E=function(e){return e};function N(e,t){if(e===t)return!0;var n=o(e),r=o(t);if(!n||!r)return!n&&!r&&String(e)===String(t);try{var i=Array.isArray(e),a=Array.isArray(t);if(i&&a)return e.length===t.length&&e.every(function(e,n){return N(e,t[n])});if(e instanceof Date&&t instanceof Date)return e.getTime()===t.getTime();if(i||a)return!1;var s=Object.keys(e),c=Object.keys(t);return s.length===c.length&&s.every(function(n){return N(e[n],t[n])})}catch(e){return!1}}function j(e,t){for(var n=0;n<e.length;n++)if(N(e[n],t))return n;return-1}function D(e){var t=!1;return function(){t||(t=!0,e.apply(this,arguments))}}var L="data-server-rendered",M=["component","directive","filter"],I=["beforeCreate","created","beforeMount","mounted","beforeUpdate","updated","beforeDestroy","destroyed","activated","deactivated","errorCaptured","serverPrefetch"],F={optionMergeStrategies:Object.create(null),silent:!1,productionTip:!1,devtools:!1,performance:!1,errorHandler:null,warnHandler:null,ignoredElements:[],keyCodes:Object.create(null),isReservedTag:T,isReservedAttr:T,isUnknownElement:T,getTagNamespace:S,parsePlatformTagName:E,mustUseProp:T,async:!0,_lifecycleHooks:I},P=/a-zA-Z\u00B7\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u037D\u037F-\u1FFF\u200C-\u200D\u203F-\u2040\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD/;function R(e,t,n,r){Object.defineProperty(e,t,{value:n,enumerable:!!r,writable:!0,configurable:!0})}var H=new RegExp("[^"+P.source+".$_\\d]");var B,U="__proto__"in{},z="undefined"!=typeof window,V="undefined"!=typeof WXEnvironment&&!!WXEnvironment.platform,K=V&&WXEnvironment.platform.toLowerCase(),J=z&&window.navigator.userAgent.toLowerCase(),q=J&&/msie|trident/.test(J),W=J&&J.indexOf("msie 9.0")>0,Z=J&&J.indexOf("edge/")>0,G=(J&&J.indexOf("android"),J&&/iphone|ipad|ipod|ios/.test(J)||"ios"===K),X=(J&&/chrome\/\d+/.test(J),J&&/phantomjs/.test(J),J&&J.match(/firefox\/(\d+)/)),Y={}.watch,Q=!1;if(z)try{var ee={};Object.defineProperty(ee,"passive",{get:function(){Q=!0}}),window.addEventListener("test-passive",null,ee)}catch(e){}var te=function(){return void 0===B&&(B=!z&&!V&&"undefined"!=typeof global&&(global.process&&"server"===global.process.env.VUE_ENV)),B},ne=z&&window.__VUE_DEVTOOLS_GLOBAL_HOOK__;function re(e){return"function"==typeof e&&/native code/.test(e.toString())}var ie,oe="undefined"!=typeof Symbol&&re(Symbol)&&"undefined"!=typeof Reflect&&re(Reflect.ownKeys);ie="undefined"!=typeof Set&&re(Set)?Set:function(){function e(){this.set=Object.create(null)}return e.prototype.has=function(e){return!0===this.set[e]},e.prototype.add=function(e){this.set[e]=!0},e.prototype.clear=function(){this.set=Object.create(null)},e}();var ae=S,se=0,ce=function(){this.id=se++,this.subs=[]};ce.prototype.addSub=function(e){this.subs.push(e)},ce.prototype.removeSub=function(e){h(this.subs,e)},ce.prototype.depend=function(){ce.target&&ce.target.addDep(this)},ce.prototype.notify=function(){for(var e=this.subs.slice(),t=0,n=e.length;t<n;t++)e[t].update()},ce.target=null;var ue=[];function le(e){ue.push(e),ce.target=e}function fe(){ue.pop(),ce.target=ue[ue.length-1]}var pe=function(e,t,n,r,i,o,a,s){this.tag=e,this.data=t,this.children=n,this.text=r,this.elm=i,this.ns=void 0,this.context=o,this.fnContext=void 0,this.fnOptions=void 0,this.fnScopeId=void 0,this.key=t&&t.key,this.componentOptions=a,this.componentInstance=void 0,this.parent=void 0,this.raw=!1,this.isStatic=!1,this.isRootInsert=!0,this.isComment=!1,this.isCloned=!1,this.isOnce=!1,this.asyncFactory=s,this.asyncMeta=void 0,this.isAsyncPlaceholder=!1},de={child:{configurable:!0}};de.child.get=function(){return this.componentInstance},Object.defineProperties(pe.prototype,de);var ve=function(e){void 0===e&&(e="");var t=new pe;return t.text=e,t.isComment=!0,t};function he(e){return new pe(void 0,void 0,void 0,String(e))}function me(e){var t=new pe(e.tag,e.data,e.children&&e.children.slice(),e.text,e.elm,e.context,e.componentOptions,e.asyncFactory);return t.ns=e.ns,t.isStatic=e.isStatic,t.key=e.key,t.isComment=e.isComment,t.fnContext=e.fnContext,t.fnOptions=e.fnOptions,t.fnScopeId=e.fnScopeId,t.asyncMeta=e.asyncMeta,t.isCloned=!0,t}var ye=Array.prototype,ge=Object.create(ye);["push","pop","shift","unshift","splice","sort","reverse"].forEach(function(e){var t=ye[e];R(ge,e,function(){for(var n=[],r=arguments.length;r--;)n[r]=arguments[r];var i,o=t.apply(this,n),a=this.__ob__;switch(e){case"push":case"unshift":i=n;break;case"splice":i=n.slice(2)}return i&&a.observeArray(i),a.dep.notify(),o})});var _e=Object.getOwnPropertyNames(ge),be=!0;function $e(e){be=e}var we=function(e){var t;this.value=e,this.dep=new ce,this.vmCount=0,R(e,"__ob__",this),Array.isArray(e)?(U?(t=ge,e.__proto__=t):function(e,t,n){for(var r=0,i=n.length;r<i;r++){var o=n[r];R(e,o,t[o])}}(e,ge,_e),this.observeArray(e)):this.walk(e)};function Ce(e,t){var n;if(o(e)&&!(e instanceof pe))return y(e,"__ob__")&&e.__ob__ instanceof we?n=e.__ob__:be&&!te()&&(Array.isArray(e)||s(e))&&Object.isExtensible(e)&&!e._isVue&&(n=new we(e)),t&&n&&n.vmCount++,n}function xe(e,t,n,r,i){var o=new ce,a=Object.getOwnPropertyDescriptor(e,t);if(!a||!1!==a.configurable){var s=a&&a.get,c=a&&a.set;s&&!c||2!==arguments.length||(n=e[t]);var u=!i&&Ce(n);Object.defineProperty(e,t,{enumerable:!0,configurable:!0,get:function(){var t=s?s.call(e):n;return ce.target&&(o.depend(),u&&(u.dep.depend(),Array.isArray(t)&&function e(t){for(var n=void 0,r=0,i=t.length;r<i;r++)(n=t[r])&&n.__ob__&&n.__ob__.dep.depend(),Array.isArray(n)&&e(n)}(t))),t},set:function(t){var r=s?s.call(e):n;t===r||t!=t&&r!=r||s&&!c||(c?c.call(e,t):n=t,u=!i&&Ce(t),o.notify())}})}}function ke(e,t,n){if(Array.isArray(e)&&c(t))return e.length=Math.max(e.length,t),e.splice(t,1,n),n;if(t in e&&!(t in Object.prototype))return e[t]=n,n;var r=e.__ob__;return e._isVue||r&&r.vmCount?n:r?(xe(r.value,t,n),r.dep.notify(),n):(e[t]=n,n)}function Ae(e,t){if(Array.isArray(e)&&c(t))e.splice(t,1);else{var n=e.__ob__;e._isVue||n&&n.vmCount||y(e,t)&&(delete e[t],n&&n.dep.notify())}}we.prototype.walk=function(e){for(var t=Object.keys(e),n=0;n<t.length;n++)xe(e,t[n])},we.prototype.observeArray=function(e){for(var t=0,n=e.length;t<n;t++)Ce(e[t])};var Oe=F.optionMergeStrategies;function Se(e,t){if(!t)return e;for(var n,r,i,o=oe?Reflect.ownKeys(t):Object.keys(t),a=0;a<o.length;a++)"__ob__"!==(n=o[a])&&(r=e[n],i=t[n],y(e,n)?r!==i&&s(r)&&s(i)&&Se(r,i):ke(e,n,i));return e}function Te(e,t,n){return n?function(){var r="function"==typeof t?t.call(n,n):t,i="function"==typeof e?e.call(n,n):e;return r?Se(r,i):i}:t?e?function(){return Se("function"==typeof t?t.call(this,this):t,"function"==typeof e?e.call(this,this):e)}:t:e}function Ee(e,t){var n=t?e?e.concat(t):Array.isArray(t)?t:[t]:e;return n?function(e){for(var t=[],n=0;n<e.length;n++)-1===t.indexOf(e[n])&&t.push(e[n]);return t}(n):n}function Ne(e,t,n,r){var i=Object.create(e||null);return t?A(i,t):i}Oe.data=function(e,t,n){return n?Te(e,t,n):t&&"function"!=typeof t?e:Te(e,t)},I.forEach(function(e){Oe[e]=Ee}),M.forEach(function(e){Oe[e+"s"]=Ne}),Oe.watch=function(e,t,n,r){if(e===Y&&(e=void 0),t===Y&&(t=void 0),!t)return Object.create(e||null);if(!e)return t;var i={};for(var o in A(i,e),t){var a=i[o],s=t[o];a&&!Array.isArray(a)&&(a=[a]),i[o]=a?a.concat(s):Array.isArray(s)?s:[s]}return i},Oe.props=Oe.methods=Oe.inject=Oe.computed=function(e,t,n,r){if(!e)return t;var i=Object.create(null);return A(i,e),t&&A(i,t),i},Oe.provide=Te;var je=function(e,t){return void 0===t?e:t};function De(e,t,n){if("function"==typeof t&&(t=t.options),function(e,t){var n=e.props;if(n){var r,i,o={};if(Array.isArray(n))for(r=n.length;r--;)"string"==typeof(i=n[r])&&(o[b(i)]={type:null});else if(s(n))for(var a in n)i=n[a],o[b(a)]=s(i)?i:{type:i};e.props=o}}(t),function(e,t){var n=e.inject;if(n){var r=e.inject={};if(Array.isArray(n))for(var i=0;i<n.length;i++)r[n[i]]={from:n[i]};else if(s(n))for(var o in n){var a=n[o];r[o]=s(a)?A({from:o},a):{from:a}}}}(t),function(e){var t=e.directives;if(t)for(var n in t){var r=t[n];"function"==typeof r&&(t[n]={bind:r,update:r})}}(t),!t._base&&(t.extends&&(e=De(e,t.extends,n)),t.mixins))for(var r=0,i=t.mixins.length;r<i;r++)e=De(e,t.mixins[r],n);var o,a={};for(o in e)c(o);for(o in t)y(e,o)||c(o);function c(r){var i=Oe[r]||je;a[r]=i(e[r],t[r],n,r)}return a}function Le(e,t,n,r){if("string"==typeof n){var i=e[t];if(y(i,n))return i[n];var o=b(n);if(y(i,o))return i[o];var a=$(o);return y(i,a)?i[a]:i[n]||i[o]||i[a]}}function Me(e,t,n,r){var i=t[e],o=!y(n,e),a=n[e],s=Pe(Boolean,i.type);if(s>-1)if(o&&!y(i,"default"))a=!1;else if(""===a||a===C(e)){var c=Pe(String,i.type);(c<0||s<c)&&(a=!0)}if(void 0===a){a=function(e,t,n){if(!y(t,"default"))return;var r=t.default;if(e&&e.$options.propsData&&void 0===e.$options.propsData[n]&&void 0!==e._props[n])return e._props[n];return"function"==typeof r&&"Function"!==Ie(t.type)?r.call(e):r}(r,i,e);var u=be;$e(!0),Ce(a),$e(u)}return a}function Ie(e){var t=e&&e.toString().match(/^\s*function (\w+)/);return t?t[1]:""}function Fe(e,t){return Ie(e)===Ie(t)}function Pe(e,t){if(!Array.isArray(t))return Fe(t,e)?0:-1;for(var n=0,r=t.length;n<r;n++)if(Fe(t[n],e))return n;return-1}function Re(e,t,n){le();try{if(t)for(var r=t;r=r.$parent;){var i=r.$options.errorCaptured;if(i)for(var o=0;o<i.length;o++)try{if(!1===i[o].call(r,e,t,n))return}catch(e){Be(e,r,"errorCaptured hook")}}Be(e,t,n)}finally{fe()}}function He(e,t,n,r,i){var o;try{(o=n?e.apply(t,n):e.call(t))&&!o._isVue&&u(o)&&!o._handled&&(o.catch(function(e){return Re(e,r,i+" (Promise/async)")}),o._handled=!0)}catch(e){Re(e,r,i)}return o}function Be(e,t,n){if(F.errorHandler)try{return F.errorHandler.call(null,e,t,n)}catch(t){t!==e&&Ue(t,null,"config.errorHandler")}Ue(e,t,n)}function Ue(e,t,n){if(!z&&!V||"undefined"==typeof console)throw e;console.error(e)}var ze,Ve=!1,Ke=[],Je=!1;function qe(){Je=!1;var e=Ke.slice(0);Ke.length=0;for(var t=0;t<e.length;t++)e[t]()}if("undefined"!=typeof Promise&&re(Promise)){var We=Promise.resolve();ze=function(){We.then(qe),G&&setTimeout(S)},Ve=!0}else if(q||"undefined"==typeof MutationObserver||!re(MutationObserver)&&"[object MutationObserverConstructor]"!==MutationObserver.toString())ze="undefined"!=typeof setImmediate&&re(setImmediate)?function(){setImmediate(qe)}:function(){setTimeout(qe,0)};else{var Ze=1,Ge=new MutationObserver(qe),Xe=document.createTextNode(String(Ze));Ge.observe(Xe,{characterData:!0}),ze=function(){Ze=(Ze+1)%2,Xe.data=String(Ze)},Ve=!0}function Ye(e,t){var n;if(Ke.push(function(){if(e)try{e.call(t)}catch(e){Re(e,t,"nextTick")}else n&&n(t)}),Je||(Je=!0,ze()),!e&&"undefined"!=typeof Promise)return new Promise(function(e){n=e})}var Qe=new ie;function et(e){!function e(t,n){var r,i;var a=Array.isArray(t);if(!a&&!o(t)||Object.isFrozen(t)||t instanceof pe)return;if(t.__ob__){var s=t.__ob__.dep.id;if(n.has(s))return;n.add(s)}if(a)for(r=t.length;r--;)e(t[r],n);else for(i=Object.keys(t),r=i.length;r--;)e(t[i[r]],n)}(e,Qe),Qe.clear()}var tt=g(function(e){var t="&"===e.charAt(0),n="~"===(e=t?e.slice(1):e).charAt(0),r="!"===(e=n?e.slice(1):e).charAt(0);return{name:e=r?e.slice(1):e,once:n,capture:r,passive:t}});function nt(e,t){function n(){var e=arguments,r=n.fns;if(!Array.isArray(r))return He(r,null,arguments,t,"v-on handler");for(var i=r.slice(),o=0;o<i.length;o++)He(i[o],null,e,t,"v-on handler")}return n.fns=e,n}function rt(e,n,i,o,a,s){var c,u,l,f;for(c in e)u=e[c],l=n[c],f=tt(c),t(u)||(t(l)?(t(u.fns)&&(u=e[c]=nt(u,s)),r(f.once)&&(u=e[c]=a(f.name,u,f.capture)),i(f.name,u,f.capture,f.passive,f.params)):u!==l&&(l.fns=u,e[c]=l));for(c in n)t(e[c])&&o((f=tt(c)).name,n[c],f.capture)}function it(e,i,o){var a;e instanceof pe&&(e=e.data.hook||(e.data.hook={}));var s=e[i];function c(){o.apply(this,arguments),h(a.fns,c)}t(s)?a=nt([c]):n(s.fns)&&r(s.merged)?(a=s).fns.push(c):a=nt([s,c]),a.merged=!0,e[i]=a}function ot(e,t,r,i,o){if(n(t)){if(y(t,r))return e[r]=t[r],o||delete t[r],!0;if(y(t,i))return e[r]=t[i],o||delete t[i],!0}return!1}function at(e){return i(e)?[he(e)]:Array.isArray(e)?function e(o,a){var s=[];var c,u,l,f;for(c=0;c<o.length;c++)t(u=o[c])||"boolean"==typeof u||(l=s.length-1,f=s[l],Array.isArray(u)?u.length>0&&(st((u=e(u,(a||"")+"_"+c))[0])&&st(f)&&(s[l]=he(f.text+u[0].text),u.shift()),s.push.apply(s,u)):i(u)?st(f)?s[l]=he(f.text+u):""!==u&&s.push(he(u)):st(u)&&st(f)?s[l]=he(f.text+u.text):(r(o._isVList)&&n(u.tag)&&t(u.key)&&n(a)&&(u.key="__vlist"+a+"_"+c+"__"),s.push(u)));return s}(e):void 0}function st(e){return n(e)&&n(e.text)&&!1===e.isComment}function ct(e,t){if(e){for(var n=Object.create(null),r=oe?Reflect.ownKeys(e):Object.keys(e),i=0;i<r.length;i++){var o=r[i];if("__ob__"!==o){for(var a=e[o].from,s=t;s;){if(s._provided&&y(s._provided,a)){n[o]=s._provided[a];break}s=s.$parent}if(!s&&"default"in e[o]){var c=e[o].default;n[o]="function"==typeof c?c.call(t):c}}}return n}}function ut(e,t){if(!e||!e.length)return{};for(var n={},r=0,i=e.length;r<i;r++){var o=e[r],a=o.data;if(a&&a.attrs&&a.attrs.slot&&delete a.attrs.slot,o.context!==t&&o.fnContext!==t||!a||null==a.slot)(n.default||(n.default=[])).push(o);else{var s=a.slot,c=n[s]||(n[s]=[]);"template"===o.tag?c.push.apply(c,o.children||[]):c.push(o)}}for(var u in n)n[u].every(lt)&&delete n[u];return n}function lt(e){return e.isComment&&!e.asyncFactory||" "===e.text}function ft(t,n,r){var i,o=Object.keys(n).length>0,a=t?!!t.$stable:!o,s=t&&t.$key;if(t){if(t._normalized)return t._normalized;if(a&&r&&r!==e&&s===r.$key&&!o&&!r.$hasNormal)return r;for(var c in i={},t)t[c]&&"$"!==c[0]&&(i[c]=pt(n,c,t[c]))}else i={};for(var u in n)u in i||(i[u]=dt(n,u));return t&&Object.isExtensible(t)&&(t._normalized=i),R(i,"$stable",a),R(i,"$key",s),R(i,"$hasNormal",o),i}function pt(e,t,n){var r=function(){var e=arguments.length?n.apply(null,arguments):n({});return(e=e&&"object"==typeof e&&!Array.isArray(e)?[e]:at(e))&&(0===e.length||1===e.length&&e[0].isComment)?void 0:e};return n.proxy&&Object.defineProperty(e,t,{get:r,enumerable:!0,configurable:!0}),r}function dt(e,t){return function(){return e[t]}}function vt(e,t){var r,i,a,s,c;if(Array.isArray(e)||"string"==typeof e)for(r=new Array(e.length),i=0,a=e.length;i<a;i++)r[i]=t(e[i],i);else if("number"==typeof e)for(r=new Array(e),i=0;i<e;i++)r[i]=t(i+1,i);else if(o(e))if(oe&&e[Symbol.iterator]){r=[];for(var u=e[Symbol.iterator](),l=u.next();!l.done;)r.push(t(l.value,r.length)),l=u.next()}else for(s=Object.keys(e),r=new Array(s.length),i=0,a=s.length;i<a;i++)c=s[i],r[i]=t(e[c],c,i);return n(r)||(r=[]),r._isVList=!0,r}function ht(e,t,n,r){var i,o=this.$scopedSlots[e];o?(n=n||{},r&&(n=A(A({},r),n)),i=o(n)||t):i=this.$slots[e]||t;var a=n&&n.slot;return a?this.$createElement("template",{slot:a},i):i}function mt(e){return Le(this.$options,"filters",e)||E}function yt(e,t){return Array.isArray(e)?-1===e.indexOf(t):e!==t}function gt(e,t,n,r,i){var o=F.keyCodes[t]||n;return i&&r&&!F.keyCodes[t]?yt(i,r):o?yt(o,e):r?C(r)!==t:void 0}function _t(e,t,n,r,i){if(n)if(o(n)){var a;Array.isArray(n)&&(n=O(n));var s=function(o){if("class"===o||"style"===o||v(o))a=e;else{var s=e.attrs&&e.attrs.type;a=r||F.mustUseProp(t,s,o)?e.domProps||(e.domProps={}):e.attrs||(e.attrs={})}var c=b(o),u=C(o);c in a||u in a||(a[o]=n[o],i&&((e.on||(e.on={}))["update:"+o]=function(e){n[o]=e}))};for(var c in n)s(c)}else;return e}function bt(e,t){var n=this._staticTrees||(this._staticTrees=[]),r=n[e];return r&&!t?r:(wt(r=n[e]=this.$options.staticRenderFns[e].call(this._renderProxy,null,this),"__static__"+e,!1),r)}function $t(e,t,n){return wt(e,"__once__"+t+(n?"_"+n:""),!0),e}function wt(e,t,n){if(Array.isArray(e))for(var r=0;r<e.length;r++)e[r]&&"string"!=typeof e[r]&&Ct(e[r],t+"_"+r,n);else Ct(e,t,n)}function Ct(e,t,n){e.isStatic=!0,e.key=t,e.isOnce=n}function xt(e,t){if(t)if(s(t)){var n=e.on=e.on?A({},e.on):{};for(var r in t){var i=n[r],o=t[r];n[r]=i?[].concat(i,o):o}}else;return e}function kt(e,t,n,r){t=t||{$stable:!n};for(var i=0;i<e.length;i++){var o=e[i];Array.isArray(o)?kt(o,t,n):o&&(o.proxy&&(o.fn.proxy=!0),t[o.key]=o.fn)}return r&&(t.$key=r),t}function At(e,t){for(var n=0;n<t.length;n+=2){var r=t[n];"string"==typeof r&&r&&(e[t[n]]=t[n+1])}return e}function Ot(e,t){return"string"==typeof e?t+e:e}function St(e){e._o=$t,e._n=f,e._s=l,e._l=vt,e._t=ht,e._q=N,e._i=j,e._m=bt,e._f=mt,e._k=gt,e._b=_t,e._v=he,e._e=ve,e._u=kt,e._g=xt,e._d=At,e._p=Ot}function Tt(t,n,i,o,a){var s,c=this,u=a.options;y(o,"_uid")?(s=Object.create(o))._original=o:(s=o,o=o._original);var l=r(u._compiled),f=!l;this.data=t,this.props=n,this.children=i,this.parent=o,this.listeners=t.on||e,this.injections=ct(u.inject,o),this.slots=function(){return c.$slots||ft(t.scopedSlots,c.$slots=ut(i,o)),c.$slots},Object.defineProperty(this,"scopedSlots",{enumerable:!0,get:function(){return ft(t.scopedSlots,this.slots())}}),l&&(this.$options=u,this.$slots=this.slots(),this.$scopedSlots=ft(t.scopedSlots,this.$slots)),u._scopeId?this._c=function(e,t,n,r){var i=Pt(s,e,t,n,r,f);return i&&!Array.isArray(i)&&(i.fnScopeId=u._scopeId,i.fnContext=o),i}:this._c=function(e,t,n,r){return Pt(s,e,t,n,r,f)}}function Et(e,t,n,r,i){var o=me(e);return o.fnContext=n,o.fnOptions=r,t.slot&&((o.data||(o.data={})).slot=t.slot),o}function Nt(e,t){for(var n in t)e[b(n)]=t[n]}St(Tt.prototype);var jt={init:function(e,t){if(e.componentInstance&&!e.componentInstance._isDestroyed&&e.data.keepAlive){var r=e;jt.prepatch(r,r)}else{(e.componentInstance=function(e,t){var r={_isComponent:!0,_parentVnode:e,parent:t},i=e.data.inlineTemplate;n(i)&&(r.render=i.render,r.staticRenderFns=i.staticRenderFns);return new e.componentOptions.Ctor(r)}(e,Wt)).$mount(t?e.elm:void 0,t)}},prepatch:function(t,n){var r=n.componentOptions;!function(t,n,r,i,o){var a=i.data.scopedSlots,s=t.$scopedSlots,c=!!(a&&!a.$stable||s!==e&&!s.$stable||a&&t.$scopedSlots.$key!==a.$key),u=!!(o||t.$options._renderChildren||c);t.$options._parentVnode=i,t.$vnode=i,t._vnode&&(t._vnode.parent=i);if(t.$options._renderChildren=o,t.$attrs=i.data.attrs||e,t.$listeners=r||e,n&&t.$options.props){$e(!1);for(var l=t._props,f=t.$options._propKeys||[],p=0;p<f.length;p++){var d=f[p],v=t.$options.props;l[d]=Me(d,v,n,t)}$e(!0),t.$options.propsData=n}r=r||e;var h=t.$options._parentListeners;t.$options._parentListeners=r,qt(t,r,h),u&&(t.$slots=ut(o,i.context),t.$forceUpdate())}(n.componentInstance=t.componentInstance,r.propsData,r.listeners,n,r.children)},insert:function(e){var t,n=e.context,r=e.componentInstance;r._isMounted||(r._isMounted=!0,Yt(r,"mounted")),e.data.keepAlive&&(n._isMounted?((t=r)._inactive=!1,en.push(t)):Xt(r,!0))},destroy:function(e){var t=e.componentInstance;t._isDestroyed||(e.data.keepAlive?function e(t,n){if(n&&(t._directInactive=!0,Gt(t)))return;if(!t._inactive){t._inactive=!0;for(var r=0;r<t.$children.length;r++)e(t.$children[r]);Yt(t,"deactivated")}}(t,!0):t.$destroy())}},Dt=Object.keys(jt);function Lt(i,a,s,c,l){if(!t(i)){var f=s.$options._base;if(o(i)&&(i=f.extend(i)),"function"==typeof i){var p;if(t(i.cid)&&void 0===(i=function(e,i){if(r(e.error)&&n(e.errorComp))return e.errorComp;if(n(e.resolved))return e.resolved;var a=Ht;a&&n(e.owners)&&-1===e.owners.indexOf(a)&&e.owners.push(a);if(r(e.loading)&&n(e.loadingComp))return e.loadingComp;if(a&&!n(e.owners)){var s=e.owners=[a],c=!0,l=null,f=null;a.$on("hook:destroyed",function(){return h(s,a)});var p=function(e){for(var t=0,n=s.length;t<n;t++)s[t].$forceUpdate();e&&(s.length=0,null!==l&&(clearTimeout(l),l=null),null!==f&&(clearTimeout(f),f=null))},d=D(function(t){e.resolved=Bt(t,i),c?s.length=0:p(!0)}),v=D(function(t){n(e.errorComp)&&(e.error=!0,p(!0))}),m=e(d,v);return o(m)&&(u(m)?t(e.resolved)&&m.then(d,v):u(m.component)&&(m.component.then(d,v),n(m.error)&&(e.errorComp=Bt(m.error,i)),n(m.loading)&&(e.loadingComp=Bt(m.loading,i),0===m.delay?e.loading=!0:l=setTimeout(function(){l=null,t(e.resolved)&&t(e.error)&&(e.loading=!0,p(!1))},m.delay||200)),n(m.timeout)&&(f=setTimeout(function(){f=null,t(e.resolved)&&v(null)},m.timeout)))),c=!1,e.loading?e.loadingComp:e.resolved}}(p=i,f)))return function(e,t,n,r,i){var o=ve();return o.asyncFactory=e,o.asyncMeta={data:t,context:n,children:r,tag:i},o}(p,a,s,c,l);a=a||{},$n(i),n(a.model)&&function(e,t){var r=e.model&&e.model.prop||"value",i=e.model&&e.model.event||"input";(t.attrs||(t.attrs={}))[r]=t.model.value;var o=t.on||(t.on={}),a=o[i],s=t.model.callback;n(a)?(Array.isArray(a)?-1===a.indexOf(s):a!==s)&&(o[i]=[s].concat(a)):o[i]=s}(i.options,a);var d=function(e,r,i){var o=r.options.props;if(!t(o)){var a={},s=e.attrs,c=e.props;if(n(s)||n(c))for(var u in o){var l=C(u);ot(a,c,u,l,!0)||ot(a,s,u,l,!1)}return a}}(a,i);if(r(i.options.functional))return function(t,r,i,o,a){var s=t.options,c={},u=s.props;if(n(u))for(var l in u)c[l]=Me(l,u,r||e);else n(i.attrs)&&Nt(c,i.attrs),n(i.props)&&Nt(c,i.props);var f=new Tt(i,c,a,o,t),p=s.render.call(null,f._c,f);if(p instanceof pe)return Et(p,i,f.parent,s);if(Array.isArray(p)){for(var d=at(p)||[],v=new Array(d.length),h=0;h<d.length;h++)v[h]=Et(d[h],i,f.parent,s);return v}}(i,d,a,s,c);var v=a.on;if(a.on=a.nativeOn,r(i.options.abstract)){var m=a.slot;a={},m&&(a.slot=m)}!function(e){for(var t=e.hook||(e.hook={}),n=0;n<Dt.length;n++){var r=Dt[n],i=t[r],o=jt[r];i===o||i&&i._merged||(t[r]=i?Mt(o,i):o)}}(a);var y=i.options.name||l;return new pe("vue-component-"+i.cid+(y?"-"+y:""),a,void 0,void 0,void 0,s,{Ctor:i,propsData:d,listeners:v,tag:l,children:c},p)}}}function Mt(e,t){var n=function(n,r){e(n,r),t(n,r)};return n._merged=!0,n}var It=1,Ft=2;function Pt(e,a,s,c,u,l){return(Array.isArray(s)||i(s))&&(u=c,c=s,s=void 0),r(l)&&(u=Ft),function(e,i,a,s,c){if(n(a)&&n(a.__ob__))return ve();n(a)&&n(a.is)&&(i=a.is);if(!i)return ve();Array.isArray(s)&&"function"==typeof s[0]&&((a=a||{}).scopedSlots={default:s[0]},s.length=0);c===Ft?s=at(s):c===It&&(s=function(e){for(var t=0;t<e.length;t++)if(Array.isArray(e[t]))return Array.prototype.concat.apply([],e);return e}(s));var u,l;if("string"==typeof i){var f;l=e.$vnode&&e.$vnode.ns||F.getTagNamespace(i),u=F.isReservedTag(i)?new pe(F.parsePlatformTagName(i),a,s,void 0,void 0,e):a&&a.pre||!n(f=Le(e.$options,"components",i))?new pe(i,a,s,void 0,void 0,e):Lt(f,a,e,s,i)}else u=Lt(i,a,e,s);return Array.isArray(u)?u:n(u)?(n(l)&&function e(i,o,a){i.ns=o;"foreignObject"===i.tag&&(o=void 0,a=!0);if(n(i.children))for(var s=0,c=i.children.length;s<c;s++){var u=i.children[s];n(u.tag)&&(t(u.ns)||r(a)&&"svg"!==u.tag)&&e(u,o,a)}}(u,l),n(a)&&function(e){o(e.style)&&et(e.style);o(e.class)&&et(e.class)}(a),u):ve()}(e,a,s,c,u)}var Rt,Ht=null;function Bt(e,t){return(e.__esModule||oe&&"Module"===e[Symbol.toStringTag])&&(e=e.default),o(e)?t.extend(e):e}function Ut(e){return e.isComment&&e.asyncFactory}function zt(e){if(Array.isArray(e))for(var t=0;t<e.length;t++){var r=e[t];if(n(r)&&(n(r.componentOptions)||Ut(r)))return r}}function Vt(e,t){Rt.$on(e,t)}function Kt(e,t){Rt.$off(e,t)}function Jt(e,t){var n=Rt;return function r(){null!==t.apply(null,arguments)&&n.$off(e,r)}}function qt(e,t,n){Rt=e,rt(t,n||{},Vt,Kt,Jt,e),Rt=void 0}var Wt=null;function Zt(e){var t=Wt;return Wt=e,function(){Wt=t}}function Gt(e){for(;e&&(e=e.$parent);)if(e._inactive)return!0;return!1}function Xt(e,t){if(t){if(e._directInactive=!1,Gt(e))return}else if(e._directInactive)return;if(e._inactive||null===e._inactive){e._inactive=!1;for(var n=0;n<e.$children.length;n++)Xt(e.$children[n]);Yt(e,"activated")}}function Yt(e,t){le();var n=e.$options[t],r=t+" hook";if(n)for(var i=0,o=n.length;i<o;i++)He(n[i],e,null,e,r);e._hasHookEvent&&e.$emit("hook:"+t),fe()}var Qt=[],en=[],tn={},nn=!1,rn=!1,on=0;var an=0,sn=Date.now;if(z&&!q){var cn=window.performance;cn&&"function"==typeof cn.now&&sn()>document.createEvent("Event").timeStamp&&(sn=function(){return cn.now()})}function un(){var e,t;for(an=sn(),rn=!0,Qt.sort(function(e,t){return e.id-t.id}),on=0;on<Qt.length;on++)(e=Qt[on]).before&&e.before(),t=e.id,tn[t]=null,e.run();var n=en.slice(),r=Qt.slice();on=Qt.length=en.length=0,tn={},nn=rn=!1,function(e){for(var t=0;t<e.length;t++)e[t]._inactive=!0,Xt(e[t],!0)}(n),function(e){var t=e.length;for(;t--;){var n=e[t],r=n.vm;r._watcher===n&&r._isMounted&&!r._isDestroyed&&Yt(r,"updated")}}(r),ne&&F.devtools&&ne.emit("flush")}var ln=0,fn=function(e,t,n,r,i){this.vm=e,i&&(e._watcher=this),e._watchers.push(this),r?(this.deep=!!r.deep,this.user=!!r.user,this.lazy=!!r.lazy,this.sync=!!r.sync,this.before=r.before):this.deep=this.user=this.lazy=this.sync=!1,this.cb=n,this.id=++ln,this.active=!0,this.dirty=this.lazy,this.deps=[],this.newDeps=[],this.depIds=new ie,this.newDepIds=new ie,this.expression="","function"==typeof t?this.getter=t:(this.getter=function(e){if(!H.test(e)){var t=e.split(".");return function(e){for(var n=0;n<t.length;n++){if(!e)return;e=e[t[n]]}return e}}}(t),this.getter||(this.getter=S)),this.value=this.lazy?void 0:this.get()};fn.prototype.get=function(){var e;le(this);var t=this.vm;try{e=this.getter.call(t,t)}catch(e){if(!this.user)throw e;Re(e,t,'getter for watcher "'+this.expression+'"')}finally{this.deep&&et(e),fe(),this.cleanupDeps()}return e},fn.prototype.addDep=function(e){var t=e.id;this.newDepIds.has(t)||(this.newDepIds.add(t),this.newDeps.push(e),this.depIds.has(t)||e.addSub(this))},fn.prototype.cleanupDeps=function(){for(var e=this.deps.length;e--;){var t=this.deps[e];this.newDepIds.has(t.id)||t.removeSub(this)}var n=this.depIds;this.depIds=this.newDepIds,this.newDepIds=n,this.newDepIds.clear(),n=this.deps,this.deps=this.newDeps,this.newDeps=n,this.newDeps.length=0},fn.prototype.update=function(){this.lazy?this.dirty=!0:this.sync?this.run():function(e){var t=e.id;if(null==tn[t]){if(tn[t]=!0,rn){for(var n=Qt.length-1;n>on&&Qt[n].id>e.id;)n--;Qt.splice(n+1,0,e)}else Qt.push(e);nn||(nn=!0,Ye(un))}}(this)},fn.prototype.run=function(){if(this.active){var e=this.get();if(e!==this.value||o(e)||this.deep){var t=this.value;if(this.value=e,this.user)try{this.cb.call(this.vm,e,t)}catch(e){Re(e,this.vm,'callback for watcher "'+this.expression+'"')}else this.cb.call(this.vm,e,t)}}},fn.prototype.evaluate=function(){this.value=this.get(),this.dirty=!1},fn.prototype.depend=function(){for(var e=this.deps.length;e--;)this.deps[e].depend()},fn.prototype.teardown=function(){if(this.active){this.vm._isBeingDestroyed||h(this.vm._watchers,this);for(var e=this.deps.length;e--;)this.deps[e].removeSub(this);this.active=!1}};var pn={enumerable:!0,configurable:!0,get:S,set:S};function dn(e,t,n){pn.get=function(){return this[t][n]},pn.set=function(e){this[t][n]=e},Object.defineProperty(e,n,pn)}function vn(e){e._watchers=[];var t=e.$options;t.props&&function(e,t){var n=e.$options.propsData||{},r=e._props={},i=e.$options._propKeys=[];e.$parent&&$e(!1);var o=function(o){i.push(o);var a=Me(o,t,n,e);xe(r,o,a),o in e||dn(e,"_props",o)};for(var a in t)o(a);$e(!0)}(e,t.props),t.methods&&function(e,t){e.$options.props;for(var n in t)e[n]="function"!=typeof t[n]?S:x(t[n],e)}(e,t.methods),t.data?function(e){var t=e.$options.data;s(t=e._data="function"==typeof t?function(e,t){le();try{return e.call(t,t)}catch(e){return Re(e,t,"data()"),{}}finally{fe()}}(t,e):t||{})||(t={});var n=Object.keys(t),r=e.$options.props,i=(e.$options.methods,n.length);for(;i--;){var o=n[i];r&&y(r,o)||(a=void 0,36!==(a=(o+"").charCodeAt(0))&&95!==a&&dn(e,"_data",o))}var a;Ce(t,!0)}(e):Ce(e._data={},!0),t.computed&&function(e,t){var n=e._computedWatchers=Object.create(null),r=te();for(var i in t){var o=t[i],a="function"==typeof o?o:o.get;r||(n[i]=new fn(e,a||S,S,hn)),i in e||mn(e,i,o)}}(e,t.computed),t.watch&&t.watch!==Y&&function(e,t){for(var n in t){var r=t[n];if(Array.isArray(r))for(var i=0;i<r.length;i++)_n(e,n,r[i]);else _n(e,n,r)}}(e,t.watch)}var hn={lazy:!0};function mn(e,t,n){var r=!te();"function"==typeof n?(pn.get=r?yn(t):gn(n),pn.set=S):(pn.get=n.get?r&&!1!==n.cache?yn(t):gn(n.get):S,pn.set=n.set||S),Object.defineProperty(e,t,pn)}function yn(e){return function(){var t=this._computedWatchers&&this._computedWatchers[e];if(t)return t.dirty&&t.evaluate(),ce.target&&t.depend(),t.value}}function gn(e){return function(){return e.call(this,this)}}function _n(e,t,n,r){return s(n)&&(r=n,n=n.handler),"string"==typeof n&&(n=e[n]),e.$watch(t,n,r)}var bn=0;function $n(e){var t=e.options;if(e.super){var n=$n(e.super);if(n!==e.superOptions){e.superOptions=n;var r=function(e){var t,n=e.options,r=e.sealedOptions;for(var i in n)n[i]!==r[i]&&(t||(t={}),t[i]=n[i]);return t}(e);r&&A(e.extendOptions,r),(t=e.options=De(n,e.extendOptions)).name&&(t.components[t.name]=e)}}return t}function wn(e){this._init(e)}function Cn(e){e.cid=0;var t=1;e.extend=function(e){e=e||{};var n=this,r=n.cid,i=e._Ctor||(e._Ctor={});if(i[r])return i[r];var o=e.name||n.options.name,a=function(e){this._init(e)};return(a.prototype=Object.create(n.prototype)).constructor=a,a.cid=t++,a.options=De(n.options,e),a.super=n,a.options.props&&function(e){var t=e.options.props;for(var n in t)dn(e.prototype,"_props",n)}(a),a.options.computed&&function(e){var t=e.options.computed;for(var n in t)mn(e.prototype,n,t[n])}(a),a.extend=n.extend,a.mixin=n.mixin,a.use=n.use,M.forEach(function(e){a[e]=n[e]}),o&&(a.options.components[o]=a),a.superOptions=n.options,a.extendOptions=e,a.sealedOptions=A({},a.options),i[r]=a,a}}function xn(e){return e&&(e.Ctor.options.name||e.tag)}function kn(e,t){return Array.isArray(e)?e.indexOf(t)>-1:"string"==typeof e?e.split(",").indexOf(t)>-1:(n=e,"[object RegExp]"===a.call(n)&&e.test(t));var n}function An(e,t){var n=e.cache,r=e.keys,i=e._vnode;for(var o in n){var a=n[o];if(a){var s=xn(a.componentOptions);s&&!t(s)&&On(n,o,r,i)}}}function On(e,t,n,r){var i=e[t];!i||r&&i.tag===r.tag||i.componentInstance.$destroy(),e[t]=null,h(n,t)}!function(t){t.prototype._init=function(t){var n=this;n._uid=bn++,n._isVue=!0,t&&t._isComponent?function(e,t){var n=e.$options=Object.create(e.constructor.options),r=t._parentVnode;n.parent=t.parent,n._parentVnode=r;var i=r.componentOptions;n.propsData=i.propsData,n._parentListeners=i.listeners,n._renderChildren=i.children,n._componentTag=i.tag,t.render&&(n.render=t.render,n.staticRenderFns=t.staticRenderFns)}(n,t):n.$options=De($n(n.constructor),t||{},n),n._renderProxy=n,n._self=n,function(e){var t=e.$options,n=t.parent;if(n&&!t.abstract){for(;n.$options.abstract&&n.$parent;)n=n.$parent;n.$children.push(e)}e.$parent=n,e.$root=n?n.$root:e,e.$children=[],e.$refs={},e._watcher=null,e._inactive=null,e._directInactive=!1,e._isMounted=!1,e._isDestroyed=!1,e._isBeingDestroyed=!1}(n),function(e){e._events=Object.create(null),e._hasHookEvent=!1;var t=e.$options._parentListeners;t&&qt(e,t)}(n),function(t){t._vnode=null,t._staticTrees=null;var n=t.$options,r=t.$vnode=n._parentVnode,i=r&&r.context;t.$slots=ut(n._renderChildren,i),t.$scopedSlots=e,t._c=function(e,n,r,i){return Pt(t,e,n,r,i,!1)},t.$createElement=function(e,n,r,i){return Pt(t,e,n,r,i,!0)};var o=r&&r.data;xe(t,"$attrs",o&&o.attrs||e,null,!0),xe(t,"$listeners",n._parentListeners||e,null,!0)}(n),Yt(n,"beforeCreate"),function(e){var t=ct(e.$options.inject,e);t&&($e(!1),Object.keys(t).forEach(function(n){xe(e,n,t[n])}),$e(!0))}(n),vn(n),function(e){var t=e.$options.provide;t&&(e._provided="function"==typeof t?t.call(e):t)}(n),Yt(n,"created"),n.$options.el&&n.$mount(n.$options.el)}}(wn),function(e){var t={get:function(){return this._data}},n={get:function(){return this._props}};Object.defineProperty(e.prototype,"$data",t),Object.defineProperty(e.prototype,"$props",n),e.prototype.$set=ke,e.prototype.$delete=Ae,e.prototype.$watch=function(e,t,n){if(s(t))return _n(this,e,t,n);(n=n||{}).user=!0;var r=new fn(this,e,t,n);if(n.immediate)try{t.call(this,r.value)}catch(e){Re(e,this,'callback for immediate watcher "'+r.expression+'"')}return function(){r.teardown()}}}(wn),function(e){var t=/^hook:/;e.prototype.$on=function(e,n){var r=this;if(Array.isArray(e))for(var i=0,o=e.length;i<o;i++)r.$on(e[i],n);else(r._events[e]||(r._events[e]=[])).push(n),t.test(e)&&(r._hasHookEvent=!0);return r},e.prototype.$once=function(e,t){var n=this;function r(){n.$off(e,r),t.apply(n,arguments)}return r.fn=t,n.$on(e,r),n},e.prototype.$off=function(e,t){var n=this;if(!arguments.length)return n._events=Object.create(null),n;if(Array.isArray(e)){for(var r=0,i=e.length;r<i;r++)n.$off(e[r],t);return n}var o,a=n._events[e];if(!a)return n;if(!t)return n._events[e]=null,n;for(var s=a.length;s--;)if((o=a[s])===t||o.fn===t){a.splice(s,1);break}return n},e.prototype.$emit=function(e){var t=this._events[e];if(t){t=t.length>1?k(t):t;for(var n=k(arguments,1),r='event handler for "'+e+'"',i=0,o=t.length;i<o;i++)He(t[i],this,n,this,r)}return this}}(wn),function(e){e.prototype._update=function(e,t){var n=this,r=n.$el,i=n._vnode,o=Zt(n);n._vnode=e,n.$el=i?n.__patch__(i,e):n.__patch__(n.$el,e,t,!1),o(),r&&(r.__vue__=null),n.$el&&(n.$el.__vue__=n),n.$vnode&&n.$parent&&n.$vnode===n.$parent._vnode&&(n.$parent.$el=n.$el)},e.prototype.$forceUpdate=function(){this._watcher&&this._watcher.update()},e.prototype.$destroy=function(){var e=this;if(!e._isBeingDestroyed){Yt(e,"beforeDestroy"),e._isBeingDestroyed=!0;var t=e.$parent;!t||t._isBeingDestroyed||e.$options.abstract||h(t.$children,e),e._watcher&&e._watcher.teardown();for(var n=e._watchers.length;n--;)e._watchers[n].teardown();e._data.__ob__&&e._data.__ob__.vmCount--,e._isDestroyed=!0,e.__patch__(e._vnode,null),Yt(e,"destroyed"),e.$off(),e.$el&&(e.$el.__vue__=null),e.$vnode&&(e.$vnode.parent=null)}}}(wn),function(e){St(e.prototype),e.prototype.$nextTick=function(e){return Ye(e,this)},e.prototype._render=function(){var e,t=this,n=t.$options,r=n.render,i=n._parentVnode;i&&(t.$scopedSlots=ft(i.data.scopedSlots,t.$slots,t.$scopedSlots)),t.$vnode=i;try{Ht=t,e=r.call(t._renderProxy,t.$createElement)}catch(n){Re(n,t,"render"),e=t._vnode}finally{Ht=null}return Array.isArray(e)&&1===e.length&&(e=e[0]),e instanceof pe||(e=ve()),e.parent=i,e}}(wn);var Sn=[String,RegExp,Array],Tn={KeepAlive:{name:"keep-alive",abstract:!0,props:{include:Sn,exclude:Sn,max:[String,Number]},created:function(){this.cache=Object.create(null),this.keys=[]},destroyed:function(){for(var e in this.cache)On(this.cache,e,this.keys)},mounted:function(){var e=this;this.$watch("include",function(t){An(e,function(e){return kn(t,e)})}),this.$watch("exclude",function(t){An(e,function(e){return!kn(t,e)})})},render:function(){var e=this.$slots.default,t=zt(e),n=t&&t.componentOptions;if(n){var r=xn(n),i=this.include,o=this.exclude;if(i&&(!r||!kn(i,r))||o&&r&&kn(o,r))return t;var a=this.cache,s=this.keys,c=null==t.key?n.Ctor.cid+(n.tag?"::"+n.tag:""):t.key;a[c]?(t.componentInstance=a[c].componentInstance,h(s,c),s.push(c)):(a[c]=t,s.push(c),this.max&&s.length>parseInt(this.max)&&On(a,s[0],s,this._vnode)),t.data.keepAlive=!0}return t||e&&e[0]}}};!function(e){var t={get:function(){return F}};Object.defineProperty(e,"config",t),e.util={warn:ae,extend:A,mergeOptions:De,defineReactive:xe},e.set=ke,e.delete=Ae,e.nextTick=Ye,e.observable=function(e){return Ce(e),e},e.options=Object.create(null),M.forEach(function(t){e.options[t+"s"]=Object.create(null)}),e.options._base=e,A(e.options.components,Tn),function(e){e.use=function(e){var t=this._installedPlugins||(this._installedPlugins=[]);if(t.indexOf(e)>-1)return this;var n=k(arguments,1);return n.unshift(this),"function"==typeof e.install?e.install.apply(e,n):"function"==typeof e&&e.apply(null,n),t.push(e),this}}(e),function(e){e.mixin=function(e){return this.options=De(this.options,e),this}}(e),Cn(e),function(e){M.forEach(function(t){e[t]=function(e,n){return n?("component"===t&&s(n)&&(n.name=n.name||e,n=this.options._base.extend(n)),"directive"===t&&"function"==typeof n&&(n={bind:n,update:n}),this.options[t+"s"][e]=n,n):this.options[t+"s"][e]}})}(e)}(wn),Object.defineProperty(wn.prototype,"$isServer",{get:te}),Object.defineProperty(wn.prototype,"$ssrContext",{get:function(){return this.$vnode&&this.$vnode.ssrContext}}),Object.defineProperty(wn,"FunctionalRenderContext",{value:Tt}),wn.version="2.6.10";var En=p("style,class"),Nn=p("input,textarea,option,select,progress"),jn=function(e,t,n){return"value"===n&&Nn(e)&&"button"!==t||"selected"===n&&"option"===e||"checked"===n&&"input"===e||"muted"===n&&"video"===e},Dn=p("contenteditable,draggable,spellcheck"),Ln=p("events,caret,typing,plaintext-only"),Mn=function(e,t){return Hn(t)||"false"===t?"false":"contenteditable"===e&&Ln(t)?t:"true"},In=p("allowfullscreen,async,autofocus,autoplay,checked,compact,controls,declare,default,defaultchecked,defaultmuted,defaultselected,defer,disabled,enabled,formnovalidate,hidden,indeterminate,inert,ismap,itemscope,loop,multiple,muted,nohref,noresize,noshade,novalidate,nowrap,open,pauseonexit,readonly,required,reversed,scoped,seamless,selected,sortable,translate,truespeed,typemustmatch,visible"),Fn="http://www.w3.org/1999/xlink",Pn=function(e){return":"===e.charAt(5)&&"xlink"===e.slice(0,5)},Rn=function(e){return Pn(e)?e.slice(6,e.length):""},Hn=function(e){return null==e||!1===e};function Bn(e){for(var t=e.data,r=e,i=e;n(i.componentInstance);)(i=i.componentInstance._vnode)&&i.data&&(t=Un(i.data,t));for(;n(r=r.parent);)r&&r.data&&(t=Un(t,r.data));return function(e,t){if(n(e)||n(t))return zn(e,Vn(t));return""}(t.staticClass,t.class)}function Un(e,t){return{staticClass:zn(e.staticClass,t.staticClass),class:n(e.class)?[e.class,t.class]:t.class}}function zn(e,t){return e?t?e+" "+t:e:t||""}function Vn(e){return Array.isArray(e)?function(e){for(var t,r="",i=0,o=e.length;i<o;i++)n(t=Vn(e[i]))&&""!==t&&(r&&(r+=" "),r+=t);return r}(e):o(e)?function(e){var t="";for(var n in e)e[n]&&(t&&(t+=" "),t+=n);return t}(e):"string"==typeof e?e:""}var Kn={svg:"http://www.w3.org/2000/svg",math:"http://www.w3.org/1998/Math/MathML"},Jn=p("html,body,base,head,link,meta,style,title,address,article,aside,footer,header,h1,h2,h3,h4,h5,h6,hgroup,nav,section,div,dd,dl,dt,figcaption,figure,picture,hr,img,li,main,ol,p,pre,ul,a,b,abbr,bdi,bdo,br,cite,code,data,dfn,em,i,kbd,mark,q,rp,rt,rtc,ruby,s,samp,small,span,strong,sub,sup,time,u,var,wbr,area,audio,map,track,video,embed,object,param,source,canvas,script,noscript,del,ins,caption,col,colgroup,table,thead,tbody,td,th,tr,button,datalist,fieldset,form,input,label,legend,meter,optgroup,option,output,progress,select,textarea,details,dialog,menu,menuitem,summary,content,element,shadow,template,blockquote,iframe,tfoot"),qn=p("svg,animate,circle,clippath,cursor,defs,desc,ellipse,filter,font-face,foreignObject,g,glyph,image,line,marker,mask,missing-glyph,path,pattern,polygon,polyline,rect,switch,symbol,text,textpath,tspan,use,view",!0),Wn=function(e){return Jn(e)||qn(e)};function Zn(e){return qn(e)?"svg":"math"===e?"math":void 0}var Gn=Object.create(null);var Xn=p("text,number,password,search,email,tel,url");function Yn(e){if("string"==typeof e){var t=document.querySelector(e);return t||document.createElement("div")}return e}var Qn=Object.freeze({createElement:function(e,t){var n=document.createElement(e);return"select"!==e?n:(t.data&&t.data.attrs&&void 0!==t.data.attrs.multiple&&n.setAttribute("multiple","multiple"),n)},createElementNS:function(e,t){return document.createElementNS(Kn[e],t)},createTextNode:function(e){return document.createTextNode(e)},createComment:function(e){return document.createComment(e)},insertBefore:function(e,t,n){e.insertBefore(t,n)},removeChild:function(e,t){e.removeChild(t)},appendChild:function(e,t){e.appendChild(t)},parentNode:function(e){return e.parentNode},nextSibling:function(e){return e.nextSibling},tagName:function(e){return e.tagName},setTextContent:function(e,t){e.textContent=t},setStyleScope:function(e,t){e.setAttribute(t,"")}}),er={create:function(e,t){tr(t)},update:function(e,t){e.data.ref!==t.data.ref&&(tr(e,!0),tr(t))},destroy:function(e){tr(e,!0)}};function tr(e,t){var r=e.data.ref;if(n(r)){var i=e.context,o=e.componentInstance||e.elm,a=i.$refs;t?Array.isArray(a[r])?h(a[r],o):a[r]===o&&(a[r]=void 0):e.data.refInFor?Array.isArray(a[r])?a[r].indexOf(o)<0&&a[r].push(o):a[r]=[o]:a[r]=o}}var nr=new pe("",{},[]),rr=["create","activate","update","remove","destroy"];function ir(e,i){return e.key===i.key&&(e.tag===i.tag&&e.isComment===i.isComment&&n(e.data)===n(i.data)&&function(e,t){if("input"!==e.tag)return!0;var r,i=n(r=e.data)&&n(r=r.attrs)&&r.type,o=n(r=t.data)&&n(r=r.attrs)&&r.type;return i===o||Xn(i)&&Xn(o)}(e,i)||r(e.isAsyncPlaceholder)&&e.asyncFactory===i.asyncFactory&&t(i.asyncFactory.error))}function or(e,t,r){var i,o,a={};for(i=t;i<=r;++i)n(o=e[i].key)&&(a[o]=i);return a}var ar={create:sr,update:sr,destroy:function(e){sr(e,nr)}};function sr(e,t){(e.data.directives||t.data.directives)&&function(e,t){var n,r,i,o=e===nr,a=t===nr,s=ur(e.data.directives,e.context),c=ur(t.data.directives,t.context),u=[],l=[];for(n in c)r=s[n],i=c[n],r?(i.oldValue=r.value,i.oldArg=r.arg,fr(i,"update",t,e),i.def&&i.def.componentUpdated&&l.push(i)):(fr(i,"bind",t,e),i.def&&i.def.inserted&&u.push(i));if(u.length){var f=function(){for(var n=0;n<u.length;n++)fr(u[n],"inserted",t,e)};o?it(t,"insert",f):f()}l.length&&it(t,"postpatch",function(){for(var n=0;n<l.length;n++)fr(l[n],"componentUpdated",t,e)});if(!o)for(n in s)c[n]||fr(s[n],"unbind",e,e,a)}(e,t)}var cr=Object.create(null);function ur(e,t){var n,r,i=Object.create(null);if(!e)return i;for(n=0;n<e.length;n++)(r=e[n]).modifiers||(r.modifiers=cr),i[lr(r)]=r,r.def=Le(t.$options,"directives",r.name);return i}function lr(e){return e.rawName||e.name+"."+Object.keys(e.modifiers||{}).join(".")}function fr(e,t,n,r,i){var o=e.def&&e.def[t];if(o)try{o(n.elm,e,n,r,i)}catch(r){Re(r,n.context,"directive "+e.name+" "+t+" hook")}}var pr=[er,ar];function dr(e,r){var i=r.componentOptions;if(!(n(i)&&!1===i.Ctor.options.inheritAttrs||t(e.data.attrs)&&t(r.data.attrs))){var o,a,s=r.elm,c=e.data.attrs||{},u=r.data.attrs||{};for(o in n(u.__ob__)&&(u=r.data.attrs=A({},u)),u)a=u[o],c[o]!==a&&vr(s,o,a);for(o in(q||Z)&&u.value!==c.value&&vr(s,"value",u.value),c)t(u[o])&&(Pn(o)?s.removeAttributeNS(Fn,Rn(o)):Dn(o)||s.removeAttribute(o))}}function vr(e,t,n){e.tagName.indexOf("-")>-1?hr(e,t,n):In(t)?Hn(n)?e.removeAttribute(t):(n="allowfullscreen"===t&&"EMBED"===e.tagName?"true":t,e.setAttribute(t,n)):Dn(t)?e.setAttribute(t,Mn(t,n)):Pn(t)?Hn(n)?e.removeAttributeNS(Fn,Rn(t)):e.setAttributeNS(Fn,t,n):hr(e,t,n)}function hr(e,t,n){if(Hn(n))e.removeAttribute(t);else{if(q&&!W&&"TEXTAREA"===e.tagName&&"placeholder"===t&&""!==n&&!e.__ieph){var r=function(t){t.stopImmediatePropagation(),e.removeEventListener("input",r)};e.addEventListener("input",r),e.__ieph=!0}e.setAttribute(t,n)}}var mr={create:dr,update:dr};function yr(e,r){var i=r.elm,o=r.data,a=e.data;if(!(t(o.staticClass)&&t(o.class)&&(t(a)||t(a.staticClass)&&t(a.class)))){var s=Bn(r),c=i._transitionClasses;n(c)&&(s=zn(s,Vn(c))),s!==i._prevClass&&(i.setAttribute("class",s),i._prevClass=s)}}var gr,_r,br,$r,wr,Cr,xr={create:yr,update:yr},kr=/[\w).+\-_$\]]/;function Ar(e){var t,n,r,i,o,a=!1,s=!1,c=!1,u=!1,l=0,f=0,p=0,d=0;for(r=0;r<e.length;r++)if(n=t,t=e.charCodeAt(r),a)39===t&&92!==n&&(a=!1);else if(s)34===t&&92!==n&&(s=!1);else if(c)96===t&&92!==n&&(c=!1);else if(u)47===t&&92!==n&&(u=!1);else if(124!==t||124===e.charCodeAt(r+1)||124===e.charCodeAt(r-1)||l||f||p){switch(t){case 34:s=!0;break;case 39:a=!0;break;case 96:c=!0;break;case 40:p++;break;case 41:p--;break;case 91:f++;break;case 93:f--;break;case 123:l++;break;case 125:l--}if(47===t){for(var v=r-1,h=void 0;v>=0&&" "===(h=e.charAt(v));v--);h&&kr.test(h)||(u=!0)}}else void 0===i?(d=r+1,i=e.slice(0,r).trim()):m();function m(){(o||(o=[])).push(e.slice(d,r).trim()),d=r+1}if(void 0===i?i=e.slice(0,r).trim():0!==d&&m(),o)for(r=0;r<o.length;r++)i=Or(i,o[r]);return i}function Or(e,t){var n=t.indexOf("(");if(n<0)return'_f("'+t+'")('+e+")";var r=t.slice(0,n),i=t.slice(n+1);return'_f("'+r+'")('+e+(")"!==i?","+i:i)}function Sr(e,t){console.error("[Vue compiler]: "+e)}function Tr(e,t){return e?e.map(function(e){return e[t]}).filter(function(e){return e}):[]}function Er(e,t,n,r,i){(e.props||(e.props=[])).push(Rr({name:t,value:n,dynamic:i},r)),e.plain=!1}function Nr(e,t,n,r,i){(i?e.dynamicAttrs||(e.dynamicAttrs=[]):e.attrs||(e.attrs=[])).push(Rr({name:t,value:n,dynamic:i},r)),e.plain=!1}function jr(e,t,n,r){e.attrsMap[t]=n,e.attrsList.push(Rr({name:t,value:n},r))}function Dr(e,t,n,r,i,o,a,s){(e.directives||(e.directives=[])).push(Rr({name:t,rawName:n,value:r,arg:i,isDynamicArg:o,modifiers:a},s)),e.plain=!1}function Lr(e,t,n){return n?"_p("+t+',"'+e+'")':e+t}function Mr(t,n,r,i,o,a,s,c){var u;(i=i||e).right?c?n="("+n+")==='click'?'contextmenu':("+n+")":"click"===n&&(n="contextmenu",delete i.right):i.middle&&(c?n="("+n+")==='click'?'mouseup':("+n+")":"click"===n&&(n="mouseup")),i.capture&&(delete i.capture,n=Lr("!",n,c)),i.once&&(delete i.once,n=Lr("~",n,c)),i.passive&&(delete i.passive,n=Lr("&",n,c)),i.native?(delete i.native,u=t.nativeEvents||(t.nativeEvents={})):u=t.events||(t.events={});var l=Rr({value:r.trim(),dynamic:c},s);i!==e&&(l.modifiers=i);var f=u[n];Array.isArray(f)?o?f.unshift(l):f.push(l):u[n]=f?o?[l,f]:[f,l]:l,t.plain=!1}function Ir(e,t,n){var r=Fr(e,":"+t)||Fr(e,"v-bind:"+t);if(null!=r)return Ar(r);if(!1!==n){var i=Fr(e,t);if(null!=i)return JSON.stringify(i)}}function Fr(e,t,n){var r;if(null!=(r=e.attrsMap[t]))for(var i=e.attrsList,o=0,a=i.length;o<a;o++)if(i[o].name===t){i.splice(o,1);break}return n&&delete e.attrsMap[t],r}function Pr(e,t){for(var n=e.attrsList,r=0,i=n.length;r<i;r++){var o=n[r];if(t.test(o.name))return n.splice(r,1),o}}function Rr(e,t){return t&&(null!=t.start&&(e.start=t.start),null!=t.end&&(e.end=t.end)),e}function Hr(e,t,n){var r=n||{},i=r.number,o="$$v";r.trim&&(o="(typeof $$v === 'string'? $$v.trim(): $$v)"),i&&(o="_n("+o+")");var a=Br(t,o);e.model={value:"("+t+")",expression:JSON.stringify(t),callback:"function ($$v) {"+a+"}"}}function Br(e,t){var n=function(e){if(e=e.trim(),gr=e.length,e.indexOf("[")<0||e.lastIndexOf("]")<gr-1)return($r=e.lastIndexOf("."))>-1?{exp:e.slice(0,$r),key:'"'+e.slice($r+1)+'"'}:{exp:e,key:null};_r=e,$r=wr=Cr=0;for(;!zr();)Vr(br=Ur())?Jr(br):91===br&&Kr(br);return{exp:e.slice(0,wr),key:e.slice(wr+1,Cr)}}(e);return null===n.key?e+"="+t:"$set("+n.exp+", "+n.key+", "+t+")"}function Ur(){return _r.charCodeAt(++$r)}function zr(){return $r>=gr}function Vr(e){return 34===e||39===e}function Kr(e){var t=1;for(wr=$r;!zr();)if(Vr(e=Ur()))Jr(e);else if(91===e&&t++,93===e&&t--,0===t){Cr=$r;break}}function Jr(e){for(var t=e;!zr()&&(e=Ur())!==t;);}var qr,Wr="__r",Zr="__c";function Gr(e,t,n){var r=qr;return function i(){null!==t.apply(null,arguments)&&Qr(e,i,n,r)}}var Xr=Ve&&!(X&&Number(X[1])<=53);function Yr(e,t,n,r){if(Xr){var i=an,o=t;t=o._wrapper=function(e){if(e.target===e.currentTarget||e.timeStamp>=i||e.timeStamp<=0||e.target.ownerDocument!==document)return o.apply(this,arguments)}}qr.addEventListener(e,t,Q?{capture:n,passive:r}:n)}function Qr(e,t,n,r){(r||qr).removeEventListener(e,t._wrapper||t,n)}function ei(e,r){if(!t(e.data.on)||!t(r.data.on)){var i=r.data.on||{},o=e.data.on||{};qr=r.elm,function(e){if(n(e[Wr])){var t=q?"change":"input";e[t]=[].concat(e[Wr],e[t]||[]),delete e[Wr]}n(e[Zr])&&(e.change=[].concat(e[Zr],e.change||[]),delete e[Zr])}(i),rt(i,o,Yr,Qr,Gr,r.context),qr=void 0}}var ti,ni={create:ei,update:ei};function ri(e,r){if(!t(e.data.domProps)||!t(r.data.domProps)){var i,o,a=r.elm,s=e.data.domProps||{},c=r.data.domProps||{};for(i in n(c.__ob__)&&(c=r.data.domProps=A({},c)),s)i in c||(a[i]="");for(i in c){if(o=c[i],"textContent"===i||"innerHTML"===i){if(r.children&&(r.children.length=0),o===s[i])continue;1===a.childNodes.length&&a.removeChild(a.childNodes[0])}if("value"===i&&"PROGRESS"!==a.tagName){a._value=o;var u=t(o)?"":String(o);ii(a,u)&&(a.value=u)}else if("innerHTML"===i&&qn(a.tagName)&&t(a.innerHTML)){(ti=ti||document.createElement("div")).innerHTML="<svg>"+o+"</svg>";for(var l=ti.firstChild;a.firstChild;)a.removeChild(a.firstChild);for(;l.firstChild;)a.appendChild(l.firstChild)}else if(o!==s[i])try{a[i]=o}catch(e){}}}}function ii(e,t){return!e.composing&&("OPTION"===e.tagName||function(e,t){var n=!0;try{n=document.activeElement!==e}catch(e){}return n&&e.value!==t}(e,t)||function(e,t){var r=e.value,i=e._vModifiers;if(n(i)){if(i.number)return f(r)!==f(t);if(i.trim)return r.trim()!==t.trim()}return r!==t}(e,t))}var oi={create:ri,update:ri},ai=g(function(e){var t={},n=/:(.+)/;return e.split(/;(?![^(]*\))/g).forEach(function(e){if(e){var r=e.split(n);r.length>1&&(t[r[0].trim()]=r[1].trim())}}),t});function si(e){var t=ci(e.style);return e.staticStyle?A(e.staticStyle,t):t}function ci(e){return Array.isArray(e)?O(e):"string"==typeof e?ai(e):e}var ui,li=/^--/,fi=/\s*!important$/,pi=function(e,t,n){if(li.test(t))e.style.setProperty(t,n);else if(fi.test(n))e.style.setProperty(C(t),n.replace(fi,""),"important");else{var r=vi(t);if(Array.isArray(n))for(var i=0,o=n.length;i<o;i++)e.style[r]=n[i];else e.style[r]=n}},di=["Webkit","Moz","ms"],vi=g(function(e){if(ui=ui||document.createElement("div").style,"filter"!==(e=b(e))&&e in ui)return e;for(var t=e.charAt(0).toUpperCase()+e.slice(1),n=0;n<di.length;n++){var r=di[n]+t;if(r in ui)return r}});function hi(e,r){var i=r.data,o=e.data;if(!(t(i.staticStyle)&&t(i.style)&&t(o.staticStyle)&&t(o.style))){var a,s,c=r.elm,u=o.staticStyle,l=o.normalizedStyle||o.style||{},f=u||l,p=ci(r.data.style)||{};r.data.normalizedStyle=n(p.__ob__)?A({},p):p;var d=function(e,t){var n,r={};if(t)for(var i=e;i.componentInstance;)(i=i.componentInstance._vnode)&&i.data&&(n=si(i.data))&&A(r,n);(n=si(e.data))&&A(r,n);for(var o=e;o=o.parent;)o.data&&(n=si(o.data))&&A(r,n);return r}(r,!0);for(s in f)t(d[s])&&pi(c,s,"");for(s in d)(a=d[s])!==f[s]&&pi(c,s,null==a?"":a)}}var mi={create:hi,update:hi},yi=/\s+/;function gi(e,t){if(t&&(t=t.trim()))if(e.classList)t.indexOf(" ")>-1?t.split(yi).forEach(function(t){return e.classList.add(t)}):e.classList.add(t);else{var n=" "+(e.getAttribute("class")||"")+" ";n.indexOf(" "+t+" ")<0&&e.setAttribute("class",(n+t).trim())}}function _i(e,t){if(t&&(t=t.trim()))if(e.classList)t.indexOf(" ")>-1?t.split(yi).forEach(function(t){return e.classList.remove(t)}):e.classList.remove(t),e.classList.length||e.removeAttribute("class");else{for(var n=" "+(e.getAttribute("class")||"")+" ",r=" "+t+" ";n.indexOf(r)>=0;)n=n.replace(r," ");(n=n.trim())?e.setAttribute("class",n):e.removeAttribute("class")}}function bi(e){if(e){if("object"==typeof e){var t={};return!1!==e.css&&A(t,$i(e.name||"v")),A(t,e),t}return"string"==typeof e?$i(e):void 0}}var $i=g(function(e){return{enterClass:e+"-enter",enterToClass:e+"-enter-to",enterActiveClass:e+"-enter-active",leaveClass:e+"-leave",leaveToClass:e+"-leave-to",leaveActiveClass:e+"-leave-active"}}),wi=z&&!W,Ci="transition",xi="animation",ki="transition",Ai="transitionend",Oi="animation",Si="animationend";wi&&(void 0===window.ontransitionend&&void 0!==window.onwebkittransitionend&&(ki="WebkitTransition",Ai="webkitTransitionEnd"),void 0===window.onanimationend&&void 0!==window.onwebkitanimationend&&(Oi="WebkitAnimation",Si="webkitAnimationEnd"));var Ti=z?window.requestAnimationFrame?window.requestAnimationFrame.bind(window):setTimeout:function(e){return e()};function Ei(e){Ti(function(){Ti(e)})}function Ni(e,t){var n=e._transitionClasses||(e._transitionClasses=[]);n.indexOf(t)<0&&(n.push(t),gi(e,t))}function ji(e,t){e._transitionClasses&&h(e._transitionClasses,t),_i(e,t)}function Di(e,t,n){var r=Mi(e,t),i=r.type,o=r.timeout,a=r.propCount;if(!i)return n();var s=i===Ci?Ai:Si,c=0,u=function(){e.removeEventListener(s,l),n()},l=function(t){t.target===e&&++c>=a&&u()};setTimeout(function(){c<a&&u()},o+1),e.addEventListener(s,l)}var Li=/\b(transform|all)(,|$)/;function Mi(e,t){var n,r=window.getComputedStyle(e),i=(r[ki+"Delay"]||"").split(", "),o=(r[ki+"Duration"]||"").split(", "),a=Ii(i,o),s=(r[Oi+"Delay"]||"").split(", "),c=(r[Oi+"Duration"]||"").split(", "),u=Ii(s,c),l=0,f=0;return t===Ci?a>0&&(n=Ci,l=a,f=o.length):t===xi?u>0&&(n=xi,l=u,f=c.length):f=(n=(l=Math.max(a,u))>0?a>u?Ci:xi:null)?n===Ci?o.length:c.length:0,{type:n,timeout:l,propCount:f,hasTransform:n===Ci&&Li.test(r[ki+"Property"])}}function Ii(e,t){for(;e.length<t.length;)e=e.concat(e);return Math.max.apply(null,t.map(function(t,n){return Fi(t)+Fi(e[n])}))}function Fi(e){return 1e3*Number(e.slice(0,-1).replace(",","."))}function Pi(e,r){var i=e.elm;n(i._leaveCb)&&(i._leaveCb.cancelled=!0,i._leaveCb());var a=bi(e.data.transition);if(!t(a)&&!n(i._enterCb)&&1===i.nodeType){for(var s=a.css,c=a.type,u=a.enterClass,l=a.enterToClass,p=a.enterActiveClass,d=a.appearClass,v=a.appearToClass,h=a.appearActiveClass,m=a.beforeEnter,y=a.enter,g=a.afterEnter,_=a.enterCancelled,b=a.beforeAppear,$=a.appear,w=a.afterAppear,C=a.appearCancelled,x=a.duration,k=Wt,A=Wt.$vnode;A&&A.parent;)k=A.context,A=A.parent;var O=!k._isMounted||!e.isRootInsert;if(!O||$||""===$){var S=O&&d?d:u,T=O&&h?h:p,E=O&&v?v:l,N=O&&b||m,j=O&&"function"==typeof $?$:y,L=O&&w||g,M=O&&C||_,I=f(o(x)?x.enter:x),F=!1!==s&&!W,P=Bi(j),R=i._enterCb=D(function(){F&&(ji(i,E),ji(i,T)),R.cancelled?(F&&ji(i,S),M&&M(i)):L&&L(i),i._enterCb=null});e.data.show||it(e,"insert",function(){var t=i.parentNode,n=t&&t._pending&&t._pending[e.key];n&&n.tag===e.tag&&n.elm._leaveCb&&n.elm._leaveCb(),j&&j(i,R)}),N&&N(i),F&&(Ni(i,S),Ni(i,T),Ei(function(){ji(i,S),R.cancelled||(Ni(i,E),P||(Hi(I)?setTimeout(R,I):Di(i,c,R)))})),e.data.show&&(r&&r(),j&&j(i,R)),F||P||R()}}}function Ri(e,r){var i=e.elm;n(i._enterCb)&&(i._enterCb.cancelled=!0,i._enterCb());var a=bi(e.data.transition);if(t(a)||1!==i.nodeType)return r();if(!n(i._leaveCb)){var s=a.css,c=a.type,u=a.leaveClass,l=a.leaveToClass,p=a.leaveActiveClass,d=a.beforeLeave,v=a.leave,h=a.afterLeave,m=a.leaveCancelled,y=a.delayLeave,g=a.duration,_=!1!==s&&!W,b=Bi(v),$=f(o(g)?g.leave:g),w=i._leaveCb=D(function(){i.parentNode&&i.parentNode._pending&&(i.parentNode._pending[e.key]=null),_&&(ji(i,l),ji(i,p)),w.cancelled?(_&&ji(i,u),m&&m(i)):(r(),h&&h(i)),i._leaveCb=null});y?y(C):C()}function C(){w.cancelled||(!e.data.show&&i.parentNode&&((i.parentNode._pending||(i.parentNode._pending={}))[e.key]=e),d&&d(i),_&&(Ni(i,u),Ni(i,p),Ei(function(){ji(i,u),w.cancelled||(Ni(i,l),b||(Hi($)?setTimeout(w,$):Di(i,c,w)))})),v&&v(i,w),_||b||w())}}function Hi(e){return"number"==typeof e&&!isNaN(e)}function Bi(e){if(t(e))return!1;var r=e.fns;return n(r)?Bi(Array.isArray(r)?r[0]:r):(e._length||e.length)>1}function Ui(e,t){!0!==t.data.show&&Pi(t)}var zi=function(e){var o,a,s={},c=e.modules,u=e.nodeOps;for(o=0;o<rr.length;++o)for(s[rr[o]]=[],a=0;a<c.length;++a)n(c[a][rr[o]])&&s[rr[o]].push(c[a][rr[o]]);function l(e){var t=u.parentNode(e);n(t)&&u.removeChild(t,e)}function f(e,t,i,o,a,c,l){if(n(e.elm)&&n(c)&&(e=c[l]=me(e)),e.isRootInsert=!a,!function(e,t,i,o){var a=e.data;if(n(a)){var c=n(e.componentInstance)&&a.keepAlive;if(n(a=a.hook)&&n(a=a.init)&&a(e,!1),n(e.componentInstance))return d(e,t),v(i,e.elm,o),r(c)&&function(e,t,r,i){for(var o,a=e;a.componentInstance;)if(a=a.componentInstance._vnode,n(o=a.data)&&n(o=o.transition)){for(o=0;o<s.activate.length;++o)s.activate[o](nr,a);t.push(a);break}v(r,e.elm,i)}(e,t,i,o),!0}}(e,t,i,o)){var f=e.data,p=e.children,m=e.tag;n(m)?(e.elm=e.ns?u.createElementNS(e.ns,m):u.createElement(m,e),g(e),h(e,p,t),n(f)&&y(e,t),v(i,e.elm,o)):r(e.isComment)?(e.elm=u.createComment(e.text),v(i,e.elm,o)):(e.elm=u.createTextNode(e.text),v(i,e.elm,o))}}function d(e,t){n(e.data.pendingInsert)&&(t.push.apply(t,e.data.pendingInsert),e.data.pendingInsert=null),e.elm=e.componentInstance.$el,m(e)?(y(e,t),g(e)):(tr(e),t.push(e))}function v(e,t,r){n(e)&&(n(r)?u.parentNode(r)===e&&u.insertBefore(e,t,r):u.appendChild(e,t))}function h(e,t,n){if(Array.isArray(t))for(var r=0;r<t.length;++r)f(t[r],n,e.elm,null,!0,t,r);else i(e.text)&&u.appendChild(e.elm,u.createTextNode(String(e.text)))}function m(e){for(;e.componentInstance;)e=e.componentInstance._vnode;return n(e.tag)}function y(e,t){for(var r=0;r<s.create.length;++r)s.create[r](nr,e);n(o=e.data.hook)&&(n(o.create)&&o.create(nr,e),n(o.insert)&&t.push(e))}function g(e){var t;if(n(t=e.fnScopeId))u.setStyleScope(e.elm,t);else for(var r=e;r;)n(t=r.context)&&n(t=t.$options._scopeId)&&u.setStyleScope(e.elm,t),r=r.parent;n(t=Wt)&&t!==e.context&&t!==e.fnContext&&n(t=t.$options._scopeId)&&u.setStyleScope(e.elm,t)}function _(e,t,n,r,i,o){for(;r<=i;++r)f(n[r],o,e,t,!1,n,r)}function b(e){var t,r,i=e.data;if(n(i))for(n(t=i.hook)&&n(t=t.destroy)&&t(e),t=0;t<s.destroy.length;++t)s.destroy[t](e);if(n(t=e.children))for(r=0;r<e.children.length;++r)b(e.children[r])}function $(e,t,r,i){for(;r<=i;++r){var o=t[r];n(o)&&(n(o.tag)?(w(o),b(o)):l(o.elm))}}function w(e,t){if(n(t)||n(e.data)){var r,i=s.remove.length+1;for(n(t)?t.listeners+=i:t=function(e,t){function n(){0==--n.listeners&&l(e)}return n.listeners=t,n}(e.elm,i),n(r=e.componentInstance)&&n(r=r._vnode)&&n(r.data)&&w(r,t),r=0;r<s.remove.length;++r)s.remove[r](e,t);n(r=e.data.hook)&&n(r=r.remove)?r(e,t):t()}else l(e.elm)}function C(e,t,r,i){for(var o=r;o<i;o++){var a=t[o];if(n(a)&&ir(e,a))return o}}function x(e,i,o,a,c,l){if(e!==i){n(i.elm)&&n(a)&&(i=a[c]=me(i));var p=i.elm=e.elm;if(r(e.isAsyncPlaceholder))n(i.asyncFactory.resolved)?O(e.elm,i,o):i.isAsyncPlaceholder=!0;else if(r(i.isStatic)&&r(e.isStatic)&&i.key===e.key&&(r(i.isCloned)||r(i.isOnce)))i.componentInstance=e.componentInstance;else{var d,v=i.data;n(v)&&n(d=v.hook)&&n(d=d.prepatch)&&d(e,i);var h=e.children,y=i.children;if(n(v)&&m(i)){for(d=0;d<s.update.length;++d)s.update[d](e,i);n(d=v.hook)&&n(d=d.update)&&d(e,i)}t(i.text)?n(h)&&n(y)?h!==y&&function(e,r,i,o,a){for(var s,c,l,p=0,d=0,v=r.length-1,h=r[0],m=r[v],y=i.length-1,g=i[0],b=i[y],w=!a;p<=v&&d<=y;)t(h)?h=r[++p]:t(m)?m=r[--v]:ir(h,g)?(x(h,g,o,i,d),h=r[++p],g=i[++d]):ir(m,b)?(x(m,b,o,i,y),m=r[--v],b=i[--y]):ir(h,b)?(x(h,b,o,i,y),w&&u.insertBefore(e,h.elm,u.nextSibling(m.elm)),h=r[++p],b=i[--y]):ir(m,g)?(x(m,g,o,i,d),w&&u.insertBefore(e,m.elm,h.elm),m=r[--v],g=i[++d]):(t(s)&&(s=or(r,p,v)),t(c=n(g.key)?s[g.key]:C(g,r,p,v))?f(g,o,e,h.elm,!1,i,d):ir(l=r[c],g)?(x(l,g,o,i,d),r[c]=void 0,w&&u.insertBefore(e,l.elm,h.elm)):f(g,o,e,h.elm,!1,i,d),g=i[++d]);p>v?_(e,t(i[y+1])?null:i[y+1].elm,i,d,y,o):d>y&&$(0,r,p,v)}(p,h,y,o,l):n(y)?(n(e.text)&&u.setTextContent(p,""),_(p,null,y,0,y.length-1,o)):n(h)?$(0,h,0,h.length-1):n(e.text)&&u.setTextContent(p,""):e.text!==i.text&&u.setTextContent(p,i.text),n(v)&&n(d=v.hook)&&n(d=d.postpatch)&&d(e,i)}}}function k(e,t,i){if(r(i)&&n(e.parent))e.parent.data.pendingInsert=t;else for(var o=0;o<t.length;++o)t[o].data.hook.insert(t[o])}var A=p("attrs,class,staticClass,staticStyle,key");function O(e,t,i,o){var a,s=t.tag,c=t.data,u=t.children;if(o=o||c&&c.pre,t.elm=e,r(t.isComment)&&n(t.asyncFactory))return t.isAsyncPlaceholder=!0,!0;if(n(c)&&(n(a=c.hook)&&n(a=a.init)&&a(t,!0),n(a=t.componentInstance)))return d(t,i),!0;if(n(s)){if(n(u))if(e.hasChildNodes())if(n(a=c)&&n(a=a.domProps)&&n(a=a.innerHTML)){if(a!==e.innerHTML)return!1}else{for(var l=!0,f=e.firstChild,p=0;p<u.length;p++){if(!f||!O(f,u[p],i,o)){l=!1;break}f=f.nextSibling}if(!l||f)return!1}else h(t,u,i);if(n(c)){var v=!1;for(var m in c)if(!A(m)){v=!0,y(t,i);break}!v&&c.class&&et(c.class)}}else e.data!==t.text&&(e.data=t.text);return!0}return function(e,i,o,a){if(!t(i)){var c,l=!1,p=[];if(t(e))l=!0,f(i,p);else{var d=n(e.nodeType);if(!d&&ir(e,i))x(e,i,p,null,null,a);else{if(d){if(1===e.nodeType&&e.hasAttribute(L)&&(e.removeAttribute(L),o=!0),r(o)&&O(e,i,p))return k(i,p,!0),e;c=e,e=new pe(u.tagName(c).toLowerCase(),{},[],void 0,c)}var v=e.elm,h=u.parentNode(v);if(f(i,p,v._leaveCb?null:h,u.nextSibling(v)),n(i.parent))for(var y=i.parent,g=m(i);y;){for(var _=0;_<s.destroy.length;++_)s.destroy[_](y);if(y.elm=i.elm,g){for(var w=0;w<s.create.length;++w)s.create[w](nr,y);var C=y.data.hook.insert;if(C.merged)for(var A=1;A<C.fns.length;A++)C.fns[A]()}else tr(y);y=y.parent}n(h)?$(0,[e],0,0):n(e.tag)&&b(e)}}return k(i,p,l),i.elm}n(e)&&b(e)}}({nodeOps:Qn,modules:[mr,xr,ni,oi,mi,z?{create:Ui,activate:Ui,remove:function(e,t){!0!==e.data.show?Ri(e,t):t()}}:{}].concat(pr)});W&&document.addEventListener("selectionchange",function(){var e=document.activeElement;e&&e.vmodel&&Xi(e,"input")});var Vi={inserted:function(e,t,n,r){"select"===n.tag?(r.elm&&!r.elm._vOptions?it(n,"postpatch",function(){Vi.componentUpdated(e,t,n)}):Ki(e,t,n.context),e._vOptions=[].map.call(e.options,Wi)):("textarea"===n.tag||Xn(e.type))&&(e._vModifiers=t.modifiers,t.modifiers.lazy||(e.addEventListener("compositionstart",Zi),e.addEventListener("compositionend",Gi),e.addEventListener("change",Gi),W&&(e.vmodel=!0)))},componentUpdated:function(e,t,n){if("select"===n.tag){Ki(e,t,n.context);var r=e._vOptions,i=e._vOptions=[].map.call(e.options,Wi);if(i.some(function(e,t){return!N(e,r[t])}))(e.multiple?t.value.some(function(e){return qi(e,i)}):t.value!==t.oldValue&&qi(t.value,i))&&Xi(e,"change")}}};function Ki(e,t,n){Ji(e,t,n),(q||Z)&&setTimeout(function(){Ji(e,t,n)},0)}function Ji(e,t,n){var r=t.value,i=e.multiple;if(!i||Array.isArray(r)){for(var o,a,s=0,c=e.options.length;s<c;s++)if(a=e.options[s],i)o=j(r,Wi(a))>-1,a.selected!==o&&(a.selected=o);else if(N(Wi(a),r))return void(e.selectedIndex!==s&&(e.selectedIndex=s));i||(e.selectedIndex=-1)}}function qi(e,t){return t.every(function(t){return!N(t,e)})}function Wi(e){return"_value"in e?e._value:e.value}function Zi(e){e.target.composing=!0}function Gi(e){e.target.composing&&(e.target.composing=!1,Xi(e.target,"input"))}function Xi(e,t){var n=document.createEvent("HTMLEvents");n.initEvent(t,!0,!0),e.dispatchEvent(n)}function Yi(e){return!e.componentInstance||e.data&&e.data.transition?e:Yi(e.componentInstance._vnode)}var Qi={model:Vi,show:{bind:function(e,t,n){var r=t.value,i=(n=Yi(n)).data&&n.data.transition,o=e.__vOriginalDisplay="none"===e.style.display?"":e.style.display;r&&i?(n.data.show=!0,Pi(n,function(){e.style.display=o})):e.style.display=r?o:"none"},update:function(e,t,n){var r=t.value;!r!=!t.oldValue&&((n=Yi(n)).data&&n.data.transition?(n.data.show=!0,r?Pi(n,function(){e.style.display=e.__vOriginalDisplay}):Ri(n,function(){e.style.display="none"})):e.style.display=r?e.__vOriginalDisplay:"none")},unbind:function(e,t,n,r,i){i||(e.style.display=e.__vOriginalDisplay)}}},eo={name:String,appear:Boolean,css:Boolean,mode:String,type:String,enterClass:String,leaveClass:String,enterToClass:String,leaveToClass:String,enterActiveClass:String,leaveActiveClass:String,appearClass:String,appearActiveClass:String,appearToClass:String,duration:[Number,String,Object]};function to(e){var t=e&&e.componentOptions;return t&&t.Ctor.options.abstract?to(zt(t.children)):e}function no(e){var t={},n=e.$options;for(var r in n.propsData)t[r]=e[r];var i=n._parentListeners;for(var o in i)t[b(o)]=i[o];return t}function ro(e,t){if(/\d-keep-alive$/.test(t.tag))return e("keep-alive",{props:t.componentOptions.propsData})}var io=function(e){return e.tag||Ut(e)},oo=function(e){return"show"===e.name},ao={name:"transition",props:eo,abstract:!0,render:function(e){var t=this,n=this.$slots.default;if(n&&(n=n.filter(io)).length){var r=this.mode,o=n[0];if(function(e){for(;e=e.parent;)if(e.data.transition)return!0}(this.$vnode))return o;var a=to(o);if(!a)return o;if(this._leaving)return ro(e,o);var s="__transition-"+this._uid+"-";a.key=null==a.key?a.isComment?s+"comment":s+a.tag:i(a.key)?0===String(a.key).indexOf(s)?a.key:s+a.key:a.key;var c=(a.data||(a.data={})).transition=no(this),u=this._vnode,l=to(u);if(a.data.directives&&a.data.directives.some(oo)&&(a.data.show=!0),l&&l.data&&!function(e,t){return t.key===e.key&&t.tag===e.tag}(a,l)&&!Ut(l)&&(!l.componentInstance||!l.componentInstance._vnode.isComment)){var f=l.data.transition=A({},c);if("out-in"===r)return this._leaving=!0,it(f,"afterLeave",function(){t._leaving=!1,t.$forceUpdate()}),ro(e,o);if("in-out"===r){if(Ut(a))return u;var p,d=function(){p()};it(c,"afterEnter",d),it(c,"enterCancelled",d),it(f,"delayLeave",function(e){p=e})}}return o}}},so=A({tag:String,moveClass:String},eo);function co(e){e.elm._moveCb&&e.elm._moveCb(),e.elm._enterCb&&e.elm._enterCb()}function uo(e){e.data.newPos=e.elm.getBoundingClientRect()}function lo(e){var t=e.data.pos,n=e.data.newPos,r=t.left-n.left,i=t.top-n.top;if(r||i){e.data.moved=!0;var o=e.elm.style;o.transform=o.WebkitTransform="translate("+r+"px,"+i+"px)",o.transitionDuration="0s"}}delete so.mode;var fo={Transition:ao,TransitionGroup:{props:so,beforeMount:function(){var e=this,t=this._update;this._update=function(n,r){var i=Zt(e);e.__patch__(e._vnode,e.kept,!1,!0),e._vnode=e.kept,i(),t.call(e,n,r)}},render:function(e){for(var t=this.tag||this.$vnode.data.tag||"span",n=Object.create(null),r=this.prevChildren=this.children,i=this.$slots.default||[],o=this.children=[],a=no(this),s=0;s<i.length;s++){var c=i[s];c.tag&&null!=c.key&&0!==String(c.key).indexOf("__vlist")&&(o.push(c),n[c.key]=c,(c.data||(c.data={})).transition=a)}if(r){for(var u=[],l=[],f=0;f<r.length;f++){var p=r[f];p.data.transition=a,p.data.pos=p.elm.getBoundingClientRect(),n[p.key]?u.push(p):l.push(p)}this.kept=e(t,null,u),this.removed=l}return e(t,null,o)},updated:function(){var e=this.prevChildren,t=this.moveClass||(this.name||"v")+"-move";e.length&&this.hasMove(e[0].elm,t)&&(e.forEach(co),e.forEach(uo),e.forEach(lo),this._reflow=document.body.offsetHeight,e.forEach(function(e){if(e.data.moved){var n=e.elm,r=n.style;Ni(n,t),r.transform=r.WebkitTransform=r.transitionDuration="",n.addEventListener(Ai,n._moveCb=function e(r){r&&r.target!==n||r&&!/transform$/.test(r.propertyName)||(n.removeEventListener(Ai,e),n._moveCb=null,ji(n,t))})}}))},methods:{hasMove:function(e,t){if(!wi)return!1;if(this._hasMove)return this._hasMove;var n=e.cloneNode();e._transitionClasses&&e._transitionClasses.forEach(function(e){_i(n,e)}),gi(n,t),n.style.display="none",this.$el.appendChild(n);var r=Mi(n);return this.$el.removeChild(n),this._hasMove=r.hasTransform}}}};wn.config.mustUseProp=jn,wn.config.isReservedTag=Wn,wn.config.isReservedAttr=En,wn.config.getTagNamespace=Zn,wn.config.isUnknownElement=function(e){if(!z)return!0;if(Wn(e))return!1;if(e=e.toLowerCase(),null!=Gn[e])return Gn[e];var t=document.createElement(e);return e.indexOf("-")>-1?Gn[e]=t.constructor===window.HTMLUnknownElement||t.constructor===window.HTMLElement:Gn[e]=/HTMLUnknownElement/.test(t.toString())},A(wn.options.directives,Qi),A(wn.options.components,fo),wn.prototype.__patch__=z?zi:S,wn.prototype.$mount=function(e,t){return function(e,t,n){var r;return e.$el=t,e.$options.render||(e.$options.render=ve),Yt(e,"beforeMount"),r=function(){e._update(e._render(),n)},new fn(e,r,S,{before:function(){e._isMounted&&!e._isDestroyed&&Yt(e,"beforeUpdate")}},!0),n=!1,null==e.$vnode&&(e._isMounted=!0,Yt(e,"mounted")),e}(this,e=e&&z?Yn(e):void 0,t)},z&&setTimeout(function(){F.devtools&&ne&&ne.emit("init",wn)},0);var po=/\{\{((?:.|\r?\n)+?)\}\}/g,vo=/[-.*+?^${}()|[\]\/\\]/g,ho=g(function(e){var t=e[0].replace(vo,"\\$&"),n=e[1].replace(vo,"\\$&");return new RegExp(t+"((?:.|\\n)+?)"+n,"g")});var mo={staticKeys:["staticClass"],transformNode:function(e,t){t.warn;var n=Fr(e,"class");n&&(e.staticClass=JSON.stringify(n));var r=Ir(e,"class",!1);r&&(e.classBinding=r)},genData:function(e){var t="";return e.staticClass&&(t+="staticClass:"+e.staticClass+","),e.classBinding&&(t+="class:"+e.classBinding+","),t}};var yo,go={staticKeys:["staticStyle"],transformNode:function(e,t){t.warn;var n=Fr(e,"style");n&&(e.staticStyle=JSON.stringify(ai(n)));var r=Ir(e,"style",!1);r&&(e.styleBinding=r)},genData:function(e){var t="";return e.staticStyle&&(t+="staticStyle:"+e.staticStyle+","),e.styleBinding&&(t+="style:("+e.styleBinding+"),"),t}},_o=function(e){return(yo=yo||document.createElement("div")).innerHTML=e,yo.textContent},bo=p("area,base,br,col,embed,frame,hr,img,input,isindex,keygen,link,meta,param,source,track,wbr"),$o=p("colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr,source"),wo=p("address,article,aside,base,blockquote,body,caption,col,colgroup,dd,details,dialog,div,dl,dt,fieldset,figcaption,figure,footer,form,h1,h2,h3,h4,h5,h6,head,header,hgroup,hr,html,legend,li,menuitem,meta,optgroup,option,param,rp,rt,source,style,summary,tbody,td,tfoot,th,thead,title,tr,track"),Co=/^\s*([^\s"'<>\/=]+)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/,xo=/^\s*((?:v-[\w-]+:|@|:|#)\[[^=]+\][^\s"'<>\/=]*)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/,ko="[a-zA-Z_][\\-\\.0-9_a-zA-Z"+P.source+"]*",Ao="((?:"+ko+"\\:)?"+ko+")",Oo=new RegExp("^<"+Ao),So=/^\s*(\/?)>/,To=new RegExp("^<\\/"+Ao+"[^>]*>"),Eo=/^<!DOCTYPE [^>]+>/i,No=/^<!\--/,jo=/^<!\[/,Do=p("script,style,textarea",!0),Lo={},Mo={"&lt;":"<","&gt;":">","&quot;":'"',"&amp;":"&","&#10;":"\n","&#9;":"\t","&#39;":"'"},Io=/&(?:lt|gt|quot|amp|#39);/g,Fo=/&(?:lt|gt|quot|amp|#39|#10|#9);/g,Po=p("pre,textarea",!0),Ro=function(e,t){return e&&Po(e)&&"\n"===t[0]};function Ho(e,t){var n=t?Fo:Io;return e.replace(n,function(e){return Mo[e]})}var Bo,Uo,zo,Vo,Ko,Jo,qo,Wo,Zo=/^@|^v-on:/,Go=/^v-|^@|^:/,Xo=/([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/,Yo=/,([^,\}\]]*)(?:,([^,\}\]]*))?$/,Qo=/^\(|\)$/g,ea=/^\[.*\]$/,ta=/:(.*)$/,na=/^:|^\.|^v-bind:/,ra=/\.[^.\]]+(?=[^\]]*$)/g,ia=/^v-slot(:|$)|^#/,oa=/[\r\n]/,aa=/\s+/g,sa=g(_o),ca="_empty_";function ua(e,t,n){return{type:1,tag:e,attrsList:t,attrsMap:ma(t),rawAttrsMap:{},parent:n,children:[]}}function la(e,t){Bo=t.warn||Sr,Jo=t.isPreTag||T,qo=t.mustUseProp||T,Wo=t.getTagNamespace||T;t.isReservedTag;zo=Tr(t.modules,"transformNode"),Vo=Tr(t.modules,"preTransformNode"),Ko=Tr(t.modules,"postTransformNode"),Uo=t.delimiters;var n,r,i=[],o=!1!==t.preserveWhitespace,a=t.whitespace,s=!1,c=!1;function u(e){if(l(e),s||e.processed||(e=fa(e,t)),i.length||e===n||n.if&&(e.elseif||e.else)&&da(n,{exp:e.elseif,block:e}),r&&!e.forbidden)if(e.elseif||e.else)a=e,(u=function(e){var t=e.length;for(;t--;){if(1===e[t].type)return e[t];e.pop()}}(r.children))&&u.if&&da(u,{exp:a.elseif,block:a});else{if(e.slotScope){var o=e.slotTarget||'"default"';(r.scopedSlots||(r.scopedSlots={}))[o]=e}r.children.push(e),e.parent=r}var a,u;e.children=e.children.filter(function(e){return!e.slotScope}),l(e),e.pre&&(s=!1),Jo(e.tag)&&(c=!1);for(var f=0;f<Ko.length;f++)Ko[f](e,t)}function l(e){if(!c)for(var t;(t=e.children[e.children.length-1])&&3===t.type&&" "===t.text;)e.children.pop()}return function(e,t){for(var n,r,i=[],o=t.expectHTML,a=t.isUnaryTag||T,s=t.canBeLeftOpenTag||T,c=0;e;){if(n=e,r&&Do(r)){var u=0,l=r.toLowerCase(),f=Lo[l]||(Lo[l]=new RegExp("([\\s\\S]*?)(</"+l+"[^>]*>)","i")),p=e.replace(f,function(e,n,r){return u=r.length,Do(l)||"noscript"===l||(n=n.replace(/<!\--([\s\S]*?)-->/g,"$1").replace(/<!\[CDATA\[([\s\S]*?)]]>/g,"$1")),Ro(l,n)&&(n=n.slice(1)),t.chars&&t.chars(n),""});c+=e.length-p.length,e=p,A(l,c-u,c)}else{var d=e.indexOf("<");if(0===d){if(No.test(e)){var v=e.indexOf("--\x3e");if(v>=0){t.shouldKeepComment&&t.comment(e.substring(4,v),c,c+v+3),C(v+3);continue}}if(jo.test(e)){var h=e.indexOf("]>");if(h>=0){C(h+2);continue}}var m=e.match(Eo);if(m){C(m[0].length);continue}var y=e.match(To);if(y){var g=c;C(y[0].length),A(y[1],g,c);continue}var _=x();if(_){k(_),Ro(_.tagName,e)&&C(1);continue}}var b=void 0,$=void 0,w=void 0;if(d>=0){for($=e.slice(d);!(To.test($)||Oo.test($)||No.test($)||jo.test($)||(w=$.indexOf("<",1))<0);)d+=w,$=e.slice(d);b=e.substring(0,d)}d<0&&(b=e),b&&C(b.length),t.chars&&b&&t.chars(b,c-b.length,c)}if(e===n){t.chars&&t.chars(e);break}}function C(t){c+=t,e=e.substring(t)}function x(){var t=e.match(Oo);if(t){var n,r,i={tagName:t[1],attrs:[],start:c};for(C(t[0].length);!(n=e.match(So))&&(r=e.match(xo)||e.match(Co));)r.start=c,C(r[0].length),r.end=c,i.attrs.push(r);if(n)return i.unarySlash=n[1],C(n[0].length),i.end=c,i}}function k(e){var n=e.tagName,c=e.unarySlash;o&&("p"===r&&wo(n)&&A(r),s(n)&&r===n&&A(n));for(var u=a(n)||!!c,l=e.attrs.length,f=new Array(l),p=0;p<l;p++){var d=e.attrs[p],v=d[3]||d[4]||d[5]||"",h="a"===n&&"href"===d[1]?t.shouldDecodeNewlinesForHref:t.shouldDecodeNewlines;f[p]={name:d[1],value:Ho(v,h)}}u||(i.push({tag:n,lowerCasedTag:n.toLowerCase(),attrs:f,start:e.start,end:e.end}),r=n),t.start&&t.start(n,f,u,e.start,e.end)}function A(e,n,o){var a,s;if(null==n&&(n=c),null==o&&(o=c),e)for(s=e.toLowerCase(),a=i.length-1;a>=0&&i[a].lowerCasedTag!==s;a--);else a=0;if(a>=0){for(var u=i.length-1;u>=a;u--)t.end&&t.end(i[u].tag,n,o);i.length=a,r=a&&i[a-1].tag}else"br"===s?t.start&&t.start(e,[],!0,n,o):"p"===s&&(t.start&&t.start(e,[],!1,n,o),t.end&&t.end(e,n,o))}A()}(e,{warn:Bo,expectHTML:t.expectHTML,isUnaryTag:t.isUnaryTag,canBeLeftOpenTag:t.canBeLeftOpenTag,shouldDecodeNewlines:t.shouldDecodeNewlines,shouldDecodeNewlinesForHref:t.shouldDecodeNewlinesForHref,shouldKeepComment:t.comments,outputSourceRange:t.outputSourceRange,start:function(e,o,a,l,f){var p=r&&r.ns||Wo(e);q&&"svg"===p&&(o=function(e){for(var t=[],n=0;n<e.length;n++){var r=e[n];ya.test(r.name)||(r.name=r.name.replace(ga,""),t.push(r))}return t}(o));var d,v=ua(e,o,r);p&&(v.ns=p),"style"!==(d=v).tag&&("script"!==d.tag||d.attrsMap.type&&"text/javascript"!==d.attrsMap.type)||te()||(v.forbidden=!0);for(var h=0;h<Vo.length;h++)v=Vo[h](v,t)||v;s||(!function(e){null!=Fr(e,"v-pre")&&(e.pre=!0)}(v),v.pre&&(s=!0)),Jo(v.tag)&&(c=!0),s?function(e){var t=e.attrsList,n=t.length;if(n)for(var r=e.attrs=new Array(n),i=0;i<n;i++)r[i]={name:t[i].name,value:JSON.stringify(t[i].value)},null!=t[i].start&&(r[i].start=t[i].start,r[i].end=t[i].end);else e.pre||(e.plain=!0)}(v):v.processed||(pa(v),function(e){var t=Fr(e,"v-if");if(t)e.if=t,da(e,{exp:t,block:e});else{null!=Fr(e,"v-else")&&(e.else=!0);var n=Fr(e,"v-else-if");n&&(e.elseif=n)}}(v),function(e){null!=Fr(e,"v-once")&&(e.once=!0)}(v)),n||(n=v),a?u(v):(r=v,i.push(v))},end:function(e,t,n){var o=i[i.length-1];i.length-=1,r=i[i.length-1],u(o)},chars:function(e,t,n){if(r&&(!q||"textarea"!==r.tag||r.attrsMap.placeholder!==e)){var i,u,l,f=r.children;if(e=c||e.trim()?"script"===(i=r).tag||"style"===i.tag?e:sa(e):f.length?a?"condense"===a&&oa.test(e)?"":" ":o?" ":"":"")c||"condense"!==a||(e=e.replace(aa," ")),!s&&" "!==e&&(u=function(e,t){var n=t?ho(t):po;if(n.test(e)){for(var r,i,o,a=[],s=[],c=n.lastIndex=0;r=n.exec(e);){(i=r.index)>c&&(s.push(o=e.slice(c,i)),a.push(JSON.stringify(o)));var u=Ar(r[1].trim());a.push("_s("+u+")"),s.push({"@binding":u}),c=i+r[0].length}return c<e.length&&(s.push(o=e.slice(c)),a.push(JSON.stringify(o))),{expression:a.join("+"),tokens:s}}}(e,Uo))?l={type:2,expression:u.expression,tokens:u.tokens,text:e}:" "===e&&f.length&&" "===f[f.length-1].text||(l={type:3,text:e}),l&&f.push(l)}},comment:function(e,t,n){if(r){var i={type:3,text:e,isComment:!0};r.children.push(i)}}}),n}function fa(e,t){var n,r;(r=Ir(n=e,"key"))&&(n.key=r),e.plain=!e.key&&!e.scopedSlots&&!e.attrsList.length,function(e){var t=Ir(e,"ref");t&&(e.ref=t,e.refInFor=function(e){var t=e;for(;t;){if(void 0!==t.for)return!0;t=t.parent}return!1}(e))}(e),function(e){var t;"template"===e.tag?(t=Fr(e,"scope"),e.slotScope=t||Fr(e,"slot-scope")):(t=Fr(e,"slot-scope"))&&(e.slotScope=t);var n=Ir(e,"slot");n&&(e.slotTarget='""'===n?'"default"':n,e.slotTargetDynamic=!(!e.attrsMap[":slot"]&&!e.attrsMap["v-bind:slot"]),"template"===e.tag||e.slotScope||Nr(e,"slot",n,function(e,t){return e.rawAttrsMap[":"+t]||e.rawAttrsMap["v-bind:"+t]||e.rawAttrsMap[t]}(e,"slot")));if("template"===e.tag){var r=Pr(e,ia);if(r){var i=va(r),o=i.name,a=i.dynamic;e.slotTarget=o,e.slotTargetDynamic=a,e.slotScope=r.value||ca}}else{var s=Pr(e,ia);if(s){var c=e.scopedSlots||(e.scopedSlots={}),u=va(s),l=u.name,f=u.dynamic,p=c[l]=ua("template",[],e);p.slotTarget=l,p.slotTargetDynamic=f,p.children=e.children.filter(function(e){if(!e.slotScope)return e.parent=p,!0}),p.slotScope=s.value||ca,e.children=[],e.plain=!1}}}(e),function(e){"slot"===e.tag&&(e.slotName=Ir(e,"name"))}(e),function(e){var t;(t=Ir(e,"is"))&&(e.component=t);null!=Fr(e,"inline-template")&&(e.inlineTemplate=!0)}(e);for(var i=0;i<zo.length;i++)e=zo[i](e,t)||e;return function(e){var t,n,r,i,o,a,s,c,u=e.attrsList;for(t=0,n=u.length;t<n;t++)if(r=i=u[t].name,o=u[t].value,Go.test(r))if(e.hasBindings=!0,(a=ha(r.replace(Go,"")))&&(r=r.replace(ra,"")),na.test(r))r=r.replace(na,""),o=Ar(o),(c=ea.test(r))&&(r=r.slice(1,-1)),a&&(a.prop&&!c&&"innerHtml"===(r=b(r))&&(r="innerHTML"),a.camel&&!c&&(r=b(r)),a.sync&&(s=Br(o,"$event"),c?Mr(e,'"update:"+('+r+")",s,null,!1,0,u[t],!0):(Mr(e,"update:"+b(r),s,null,!1,0,u[t]),C(r)!==b(r)&&Mr(e,"update:"+C(r),s,null,!1,0,u[t])))),a&&a.prop||!e.component&&qo(e.tag,e.attrsMap.type,r)?Er(e,r,o,u[t],c):Nr(e,r,o,u[t],c);else if(Zo.test(r))r=r.replace(Zo,""),(c=ea.test(r))&&(r=r.slice(1,-1)),Mr(e,r,o,a,!1,0,u[t],c);else{var l=(r=r.replace(Go,"")).match(ta),f=l&&l[1];c=!1,f&&(r=r.slice(0,-(f.length+1)),ea.test(f)&&(f=f.slice(1,-1),c=!0)),Dr(e,r,i,o,f,c,a,u[t])}else Nr(e,r,JSON.stringify(o),u[t]),!e.component&&"muted"===r&&qo(e.tag,e.attrsMap.type,r)&&Er(e,r,"true",u[t])}(e),e}function pa(e){var t;if(t=Fr(e,"v-for")){var n=function(e){var t=e.match(Xo);if(!t)return;var n={};n.for=t[2].trim();var r=t[1].trim().replace(Qo,""),i=r.match(Yo);i?(n.alias=r.replace(Yo,"").trim(),n.iterator1=i[1].trim(),i[2]&&(n.iterator2=i[2].trim())):n.alias=r;return n}(t);n&&A(e,n)}}function da(e,t){e.ifConditions||(e.ifConditions=[]),e.ifConditions.push(t)}function va(e){var t=e.name.replace(ia,"");return t||"#"!==e.name[0]&&(t="default"),ea.test(t)?{name:t.slice(1,-1),dynamic:!0}:{name:'"'+t+'"',dynamic:!1}}function ha(e){var t=e.match(ra);if(t){var n={};return t.forEach(function(e){n[e.slice(1)]=!0}),n}}function ma(e){for(var t={},n=0,r=e.length;n<r;n++)t[e[n].name]=e[n].value;return t}var ya=/^xmlns:NS\d+/,ga=/^NS\d+:/;function _a(e){return ua(e.tag,e.attrsList.slice(),e.parent)}var ba=[mo,go,{preTransformNode:function(e,t){if("input"===e.tag){var n,r=e.attrsMap;if(!r["v-model"])return;if((r[":type"]||r["v-bind:type"])&&(n=Ir(e,"type")),r.type||n||!r["v-bind"]||(n="("+r["v-bind"]+").type"),n){var i=Fr(e,"v-if",!0),o=i?"&&("+i+")":"",a=null!=Fr(e,"v-else",!0),s=Fr(e,"v-else-if",!0),c=_a(e);pa(c),jr(c,"type","checkbox"),fa(c,t),c.processed=!0,c.if="("+n+")==='checkbox'"+o,da(c,{exp:c.if,block:c});var u=_a(e);Fr(u,"v-for",!0),jr(u,"type","radio"),fa(u,t),da(c,{exp:"("+n+")==='radio'"+o,block:u});var l=_a(e);return Fr(l,"v-for",!0),jr(l,":type",n),fa(l,t),da(c,{exp:i,block:l}),a?c.else=!0:s&&(c.elseif=s),c}}}}];var $a,wa,Ca={expectHTML:!0,modules:ba,directives:{model:function(e,t,n){var r=t.value,i=t.modifiers,o=e.tag,a=e.attrsMap.type;if(e.component)return Hr(e,r,i),!1;if("select"===o)!function(e,t,n){var r='var $$selectedVal = Array.prototype.filter.call($event.target.options,function(o){return o.selected}).map(function(o){var val = "_value" in o ? o._value : o.value;return '+(n&&n.number?"_n(val)":"val")+"});";r=r+" "+Br(t,"$event.target.multiple ? $$selectedVal : $$selectedVal[0]"),Mr(e,"change",r,null,!0)}(e,r,i);else if("input"===o&&"checkbox"===a)!function(e,t,n){var r=n&&n.number,i=Ir(e,"value")||"null",o=Ir(e,"true-value")||"true",a=Ir(e,"false-value")||"false";Er(e,"checked","Array.isArray("+t+")?_i("+t+","+i+")>-1"+("true"===o?":("+t+")":":_q("+t+","+o+")")),Mr(e,"change","var $$a="+t+",$$el=$event.target,$$c=$$el.checked?("+o+"):("+a+");if(Array.isArray($$a)){var $$v="+(r?"_n("+i+")":i)+",$$i=_i($$a,$$v);if($$el.checked){$$i<0&&("+Br(t,"$$a.concat([$$v])")+")}else{$$i>-1&&("+Br(t,"$$a.slice(0,$$i).concat($$a.slice($$i+1))")+")}}else{"+Br(t,"$$c")+"}",null,!0)}(e,r,i);else if("input"===o&&"radio"===a)!function(e,t,n){var r=n&&n.number,i=Ir(e,"value")||"null";Er(e,"checked","_q("+t+","+(i=r?"_n("+i+")":i)+")"),Mr(e,"change",Br(t,i),null,!0)}(e,r,i);else if("input"===o||"textarea"===o)!function(e,t,n){var r=e.attrsMap.type,i=n||{},o=i.lazy,a=i.number,s=i.trim,c=!o&&"range"!==r,u=o?"change":"range"===r?Wr:"input",l="$event.target.value";s&&(l="$event.target.value.trim()"),a&&(l="_n("+l+")");var f=Br(t,l);c&&(f="if($event.target.composing)return;"+f),Er(e,"value","("+t+")"),Mr(e,u,f,null,!0),(s||a)&&Mr(e,"blur","$forceUpdate()")}(e,r,i);else if(!F.isReservedTag(o))return Hr(e,r,i),!1;return!0},text:function(e,t){t.value&&Er(e,"textContent","_s("+t.value+")",t)},html:function(e,t){t.value&&Er(e,"innerHTML","_s("+t.value+")",t)}},isPreTag:function(e){return"pre"===e},isUnaryTag:bo,mustUseProp:jn,canBeLeftOpenTag:$o,isReservedTag:Wn,getTagNamespace:Zn,staticKeys:function(e){return e.reduce(function(e,t){return e.concat(t.staticKeys||[])},[]).join(",")}(ba)},xa=g(function(e){return p("type,tag,attrsList,attrsMap,plain,parent,children,attrs,start,end,rawAttrsMap"+(e?","+e:""))});function ka(e,t){e&&($a=xa(t.staticKeys||""),wa=t.isReservedTag||T,function e(t){t.static=function(e){if(2===e.type)return!1;if(3===e.type)return!0;return!(!e.pre&&(e.hasBindings||e.if||e.for||d(e.tag)||!wa(e.tag)||function(e){for(;e.parent;){if("template"!==(e=e.parent).tag)return!1;if(e.for)return!0}return!1}(e)||!Object.keys(e).every($a)))}(t);if(1===t.type){if(!wa(t.tag)&&"slot"!==t.tag&&null==t.attrsMap["inline-template"])return;for(var n=0,r=t.children.length;n<r;n++){var i=t.children[n];e(i),i.static||(t.static=!1)}if(t.ifConditions)for(var o=1,a=t.ifConditions.length;o<a;o++){var s=t.ifConditions[o].block;e(s),s.static||(t.static=!1)}}}(e),function e(t,n){if(1===t.type){if((t.static||t.once)&&(t.staticInFor=n),t.static&&t.children.length&&(1!==t.children.length||3!==t.children[0].type))return void(t.staticRoot=!0);if(t.staticRoot=!1,t.children)for(var r=0,i=t.children.length;r<i;r++)e(t.children[r],n||!!t.for);if(t.ifConditions)for(var o=1,a=t.ifConditions.length;o<a;o++)e(t.ifConditions[o].block,n)}}(e,!1))}var Aa=/^([\w$_]+|\([^)]*?\))\s*=>|^function\s*(?:[\w$]+)?\s*\(/,Oa=/\([^)]*?\);*$/,Sa=/^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*|\['[^']*?']|\["[^"]*?"]|\[\d+]|\[[A-Za-z_$][\w$]*])*$/,Ta={esc:27,tab:9,enter:13,space:32,up:38,left:37,right:39,down:40,delete:[8,46]},Ea={esc:["Esc","Escape"],tab:"Tab",enter:"Enter",space:[" ","Spacebar"],up:["Up","ArrowUp"],left:["Left","ArrowLeft"],right:["Right","ArrowRight"],down:["Down","ArrowDown"],delete:["Backspace","Delete","Del"]},Na=function(e){return"if("+e+")return null;"},ja={stop:"$event.stopPropagation();",prevent:"$event.preventDefault();",self:Na("$event.target !== $event.currentTarget"),ctrl:Na("!$event.ctrlKey"),shift:Na("!$event.shiftKey"),alt:Na("!$event.altKey"),meta:Na("!$event.metaKey"),left:Na("'button' in $event && $event.button !== 0"),middle:Na("'button' in $event && $event.button !== 1"),right:Na("'button' in $event && $event.button !== 2")};function Da(e,t){var n=t?"nativeOn:":"on:",r="",i="";for(var o in e){var a=La(e[o]);e[o]&&e[o].dynamic?i+=o+","+a+",":r+='"'+o+'":'+a+","}return r="{"+r.slice(0,-1)+"}",i?n+"_d("+r+",["+i.slice(0,-1)+"])":n+r}function La(e){if(!e)return"function(){}";if(Array.isArray(e))return"["+e.map(function(e){return La(e)}).join(",")+"]";var t=Sa.test(e.value),n=Aa.test(e.value),r=Sa.test(e.value.replace(Oa,""));if(e.modifiers){var i="",o="",a=[];for(var s in e.modifiers)if(ja[s])o+=ja[s],Ta[s]&&a.push(s);else if("exact"===s){var c=e.modifiers;o+=Na(["ctrl","shift","alt","meta"].filter(function(e){return!c[e]}).map(function(e){return"$event."+e+"Key"}).join("||"))}else a.push(s);return a.length&&(i+=function(e){return"if(!$event.type.indexOf('key')&&"+e.map(Ma).join("&&")+")return null;"}(a)),o&&(i+=o),"function($event){"+i+(t?"return "+e.value+"($event)":n?"return ("+e.value+")($event)":r?"return "+e.value:e.value)+"}"}return t||n?e.value:"function($event){"+(r?"return "+e.value:e.value)+"}"}function Ma(e){var t=parseInt(e,10);if(t)return"$event.keyCode!=="+t;var n=Ta[e],r=Ea[e];return"_k($event.keyCode,"+JSON.stringify(e)+","+JSON.stringify(n)+",$event.key,"+JSON.stringify(r)+")"}var Ia={on:function(e,t){e.wrapListeners=function(e){return"_g("+e+","+t.value+")"}},bind:function(e,t){e.wrapData=function(n){return"_b("+n+",'"+e.tag+"',"+t.value+","+(t.modifiers&&t.modifiers.prop?"true":"false")+(t.modifiers&&t.modifiers.sync?",true":"")+")"}},cloak:S},Fa=function(e){this.options=e,this.warn=e.warn||Sr,this.transforms=Tr(e.modules,"transformCode"),this.dataGenFns=Tr(e.modules,"genData"),this.directives=A(A({},Ia),e.directives);var t=e.isReservedTag||T;this.maybeComponent=function(e){return!!e.component||!t(e.tag)},this.onceId=0,this.staticRenderFns=[],this.pre=!1};function Pa(e,t){var n=new Fa(t);return{render:"with(this){return "+(e?Ra(e,n):'_c("div")')+"}",staticRenderFns:n.staticRenderFns}}function Ra(e,t){if(e.parent&&(e.pre=e.pre||e.parent.pre),e.staticRoot&&!e.staticProcessed)return Ha(e,t);if(e.once&&!e.onceProcessed)return Ba(e,t);if(e.for&&!e.forProcessed)return za(e,t);if(e.if&&!e.ifProcessed)return Ua(e,t);if("template"!==e.tag||e.slotTarget||t.pre){if("slot"===e.tag)return function(e,t){var n=e.slotName||'"default"',r=qa(e,t),i="_t("+n+(r?","+r:""),o=e.attrs||e.dynamicAttrs?Ga((e.attrs||[]).concat(e.dynamicAttrs||[]).map(function(e){return{name:b(e.name),value:e.value,dynamic:e.dynamic}})):null,a=e.attrsMap["v-bind"];!o&&!a||r||(i+=",null");o&&(i+=","+o);a&&(i+=(o?"":",null")+","+a);return i+")"}(e,t);var n;if(e.component)n=function(e,t,n){var r=t.inlineTemplate?null:qa(t,n,!0);return"_c("+e+","+Va(t,n)+(r?","+r:"")+")"}(e.component,e,t);else{var r;(!e.plain||e.pre&&t.maybeComponent(e))&&(r=Va(e,t));var i=e.inlineTemplate?null:qa(e,t,!0);n="_c('"+e.tag+"'"+(r?","+r:"")+(i?","+i:"")+")"}for(var o=0;o<t.transforms.length;o++)n=t.transforms[o](e,n);return n}return qa(e,t)||"void 0"}function Ha(e,t){e.staticProcessed=!0;var n=t.pre;return e.pre&&(t.pre=e.pre),t.staticRenderFns.push("with(this){return "+Ra(e,t)+"}"),t.pre=n,"_m("+(t.staticRenderFns.length-1)+(e.staticInFor?",true":"")+")"}function Ba(e,t){if(e.onceProcessed=!0,e.if&&!e.ifProcessed)return Ua(e,t);if(e.staticInFor){for(var n="",r=e.parent;r;){if(r.for){n=r.key;break}r=r.parent}return n?"_o("+Ra(e,t)+","+t.onceId+++","+n+")":Ra(e,t)}return Ha(e,t)}function Ua(e,t,n,r){return e.ifProcessed=!0,function e(t,n,r,i){if(!t.length)return i||"_e()";var o=t.shift();return o.exp?"("+o.exp+")?"+a(o.block)+":"+e(t,n,r,i):""+a(o.block);function a(e){return r?r(e,n):e.once?Ba(e,n):Ra(e,n)}}(e.ifConditions.slice(),t,n,r)}function za(e,t,n,r){var i=e.for,o=e.alias,a=e.iterator1?","+e.iterator1:"",s=e.iterator2?","+e.iterator2:"";return e.forProcessed=!0,(r||"_l")+"(("+i+"),function("+o+a+s+"){return "+(n||Ra)(e,t)+"})"}function Va(e,t){var n="{",r=function(e,t){var n=e.directives;if(!n)return;var r,i,o,a,s="directives:[",c=!1;for(r=0,i=n.length;r<i;r++){o=n[r],a=!0;var u=t.directives[o.name];u&&(a=!!u(e,o,t.warn)),a&&(c=!0,s+='{name:"'+o.name+'",rawName:"'+o.rawName+'"'+(o.value?",value:("+o.value+"),expression:"+JSON.stringify(o.value):"")+(o.arg?",arg:"+(o.isDynamicArg?o.arg:'"'+o.arg+'"'):"")+(o.modifiers?",modifiers:"+JSON.stringify(o.modifiers):"")+"},")}if(c)return s.slice(0,-1)+"]"}(e,t);r&&(n+=r+","),e.key&&(n+="key:"+e.key+","),e.ref&&(n+="ref:"+e.ref+","),e.refInFor&&(n+="refInFor:true,"),e.pre&&(n+="pre:true,"),e.component&&(n+='tag:"'+e.tag+'",');for(var i=0;i<t.dataGenFns.length;i++)n+=t.dataGenFns[i](e);if(e.attrs&&(n+="attrs:"+Ga(e.attrs)+","),e.props&&(n+="domProps:"+Ga(e.props)+","),e.events&&(n+=Da(e.events,!1)+","),e.nativeEvents&&(n+=Da(e.nativeEvents,!0)+","),e.slotTarget&&!e.slotScope&&(n+="slot:"+e.slotTarget+","),e.scopedSlots&&(n+=function(e,t,n){var r=e.for||Object.keys(t).some(function(e){var n=t[e];return n.slotTargetDynamic||n.if||n.for||Ka(n)}),i=!!e.if;if(!r)for(var o=e.parent;o;){if(o.slotScope&&o.slotScope!==ca||o.for){r=!0;break}o.if&&(i=!0),o=o.parent}var a=Object.keys(t).map(function(e){return Ja(t[e],n)}).join(",");return"scopedSlots:_u(["+a+"]"+(r?",null,true":"")+(!r&&i?",null,false,"+function(e){var t=5381,n=e.length;for(;n;)t=33*t^e.charCodeAt(--n);return t>>>0}(a):"")+")"}(e,e.scopedSlots,t)+","),e.model&&(n+="model:{value:"+e.model.value+",callback:"+e.model.callback+",expression:"+e.model.expression+"},"),e.inlineTemplate){var o=function(e,t){var n=e.children[0];if(n&&1===n.type){var r=Pa(n,t.options);return"inlineTemplate:{render:function(){"+r.render+"},staticRenderFns:["+r.staticRenderFns.map(function(e){return"function(){"+e+"}"}).join(",")+"]}"}}(e,t);o&&(n+=o+",")}return n=n.replace(/,$/,"")+"}",e.dynamicAttrs&&(n="_b("+n+',"'+e.tag+'",'+Ga(e.dynamicAttrs)+")"),e.wrapData&&(n=e.wrapData(n)),e.wrapListeners&&(n=e.wrapListeners(n)),n}function Ka(e){return 1===e.type&&("slot"===e.tag||e.children.some(Ka))}function Ja(e,t){var n=e.attrsMap["slot-scope"];if(e.if&&!e.ifProcessed&&!n)return Ua(e,t,Ja,"null");if(e.for&&!e.forProcessed)return za(e,t,Ja);var r=e.slotScope===ca?"":String(e.slotScope),i="function("+r+"){return "+("template"===e.tag?e.if&&n?"("+e.if+")?"+(qa(e,t)||"undefined")+":undefined":qa(e,t)||"undefined":Ra(e,t))+"}",o=r?"":",proxy:true";return"{key:"+(e.slotTarget||'"default"')+",fn:"+i+o+"}"}function qa(e,t,n,r,i){var o=e.children;if(o.length){var a=o[0];if(1===o.length&&a.for&&"template"!==a.tag&&"slot"!==a.tag){var s=n?t.maybeComponent(a)?",1":",0":"";return""+(r||Ra)(a,t)+s}var c=n?function(e,t){for(var n=0,r=0;r<e.length;r++){var i=e[r];if(1===i.type){if(Wa(i)||i.ifConditions&&i.ifConditions.some(function(e){return Wa(e.block)})){n=2;break}(t(i)||i.ifConditions&&i.ifConditions.some(function(e){return t(e.block)}))&&(n=1)}}return n}(o,t.maybeComponent):0,u=i||Za;return"["+o.map(function(e){return u(e,t)}).join(",")+"]"+(c?","+c:"")}}function Wa(e){return void 0!==e.for||"template"===e.tag||"slot"===e.tag}function Za(e,t){return 1===e.type?Ra(e,t):3===e.type&&e.isComment?(r=e,"_e("+JSON.stringify(r.text)+")"):"_v("+(2===(n=e).type?n.expression:Xa(JSON.stringify(n.text)))+")";var n,r}function Ga(e){for(var t="",n="",r=0;r<e.length;r++){var i=e[r],o=Xa(i.value);i.dynamic?n+=i.name+","+o+",":t+='"'+i.name+'":'+o+","}return t="{"+t.slice(0,-1)+"}",n?"_d("+t+",["+n.slice(0,-1)+"])":t}function Xa(e){return e.replace(/\u2028/g,"\\u2028").replace(/\u2029/g,"\\u2029")}new RegExp("\\b"+"do,if,for,let,new,try,var,case,else,with,await,break,catch,class,const,super,throw,while,yield,delete,export,import,return,switch,default,extends,finally,continue,debugger,function,arguments".split(",").join("\\b|\\b")+"\\b");function Ya(e,t){try{return new Function(e)}catch(n){return t.push({err:n,code:e}),S}}function Qa(e){var t=Object.create(null);return function(n,r,i){(r=A({},r)).warn;delete r.warn;var o=r.delimiters?String(r.delimiters)+n:n;if(t[o])return t[o];var a=e(n,r),s={},c=[];return s.render=Ya(a.render,c),s.staticRenderFns=a.staticRenderFns.map(function(e){return Ya(e,c)}),t[o]=s}}var es,ts,ns=(es=function(e,t){var n=la(e.trim(),t);!1!==t.optimize&&ka(n,t);var r=Pa(n,t);return{ast:n,render:r.render,staticRenderFns:r.staticRenderFns}},function(e){function t(t,n){var r=Object.create(e),i=[],o=[];if(n)for(var a in n.modules&&(r.modules=(e.modules||[]).concat(n.modules)),n.directives&&(r.directives=A(Object.create(e.directives||null),n.directives)),n)"modules"!==a&&"directives"!==a&&(r[a]=n[a]);r.warn=function(e,t,n){(n?o:i).push(e)};var s=es(t.trim(),r);return s.errors=i,s.tips=o,s}return{compile:t,compileToFunctions:Qa(t)}})(Ca),rs=(ns.compile,ns.compileToFunctions);function is(e){return(ts=ts||document.createElement("div")).innerHTML=e?'<a href="\n"/>':'<div a="\n"/>',ts.innerHTML.indexOf("&#10;")>0}var os=!!z&&is(!1),as=!!z&&is(!0),ss=g(function(e){var t=Yn(e);return t&&t.innerHTML}),cs=wn.prototype.$mount;return wn.prototype.$mount=function(e,t){if((e=e&&Yn(e))===document.body||e===document.documentElement)return this;var n=this.$options;if(!n.render){var r=n.template;if(r)if("string"==typeof r)"#"===r.charAt(0)&&(r=ss(r));else{if(!r.nodeType)return this;r=r.innerHTML}else e&&(r=function(e){if(e.outerHTML)return e.outerHTML;var t=document.createElement("div");return t.appendChild(e.cloneNode(!0)),t.innerHTML}(e));if(r){var i=rs(r,{outputSourceRange:!1,shouldDecodeNewlines:os,shouldDecodeNewlinesForHref:as,delimiters:n.delimiters,comments:n.comments},this),o=i.render,a=i.staticRenderFns;n.render=o,n.staticRenderFns=a}}return cs.call(this,e,t)},wn.compile=rs,wn});

/* app.js */

app = {
	scope: null,
	hosts: {},
	modules: [],
	menu: [],
	settings: [],
	themes: [
		{ value: "", label: "System Default" },
		{ value: "light", label: "Light" },
		{ value: "dark", label: "Dark" },
		{ value: "minimal dark", label: "Minimal" },
	],
};

monthMap = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];

time2ddmmmyyyy = function(t) {
	if(!t) return "";
	var d = new Date(t * 1e3),
		dd = ("0" + d.getDate()).slice(-2),
		dm = monthMap[d.getMonth()],
		dy = d.getFullYear();
	return dd + " " + dm + " " + dy;
};

codepages = [
	{ value: "", label: "Default: Latin (ISO 6937)" },
	{ value: "1", label: "West European (ISO 8859-1)" },
	{ value: "2", label: "East European  (ISO 8859-2)" },
	{ value: "3", label: "South European (ISO 8859-3)" },
	{ value: "4", label: "North European (ISO 8859-4)" },
	{ value: "5", label: "Cyrillic (ISO 8859-5)" },
	{ value: "6", label: "Arabic (ISO 8859-6)" },
	{ value: "7", label: "Greek (ISO 8859-7)" },
	{ value: "8", label: "Hebrew (ISO 8859-8)" },
	{ value: "9", label: "Turkish (ISO 8859-9)" },
	{ value: "10", label: "Nordic (ISO 8859-10)" },
	{ value: "11", label: "Thai (ISO 8859-11)" },
	{ value: "13", label: "Baltic (ISO 8859-13)" },
	{ value: "15", label: "West European (ISO 8859-15)" },
	{ value: "21", label: "UTF-8" },
];

dvbPolarization = [
	{ value: "" },
	{ value: "V", label: "Vertical" },
	{ value: "H", label: "Horizontal" },
	{ value: "-", label: "----", disabled: true },
	{ value: "R", label: "Right" },
	{ value: "L", label: "Left" },
];

dvbFec = [
	{ value: "", label: "Default: Auto" },
	{ value: "NONE" },
	{ value: "1/2" },
	{ value: "2/3" },
	{ value: "3/4" },
	{ value: "4/5" },
	{ value: "5/6" },
	{ value: "6/7" },
	{ value: "7/8" },
	{ value: "8/9" },
	{ value: "3/5" },
	{ value: "9/10" },
	{ value: "2/5" },
];

dvbsModulation = [
	{ value: "", label: "Default: not set" },
	{ value: "QPSK" },
	{ value: "PSK8", label: "8PSK" },
	{ value: "QAM16", label: "16-QAM" },
];

dvbcModulation = [
	{ value: "", label: "Default: not set" },
	{ value: "QAM16", label: "16-QAM" },
	{ value: "QAM32", label: "32-QAM" },
	{ value: "QAM64", label: "64-QAM" },
	{ value: "QAM128", label: "128-QAM" },
	{ value: "QAM256", label: "256-QAM" },
];

dvbtModulation = [
	{ value: "", label: "Default: not set" },
	{ value: "QPSK" },
	{ value: "QAM16", label: "16-QAM" },
	{ value: "QAM64", label: "64-QAM" },
];

validateId = function(value) {
	if(value == undefined || value == "") return true;
	return /^[^\\\/&%\.+ ]*$/.test(value);
};

validatePort = function(value) {
	if(value == undefined || value == "") return true;
	value = Number(value);
	return !isNaN(value) && value > 0 && value <= 65535;
};

validateHostPort = function(value) {
	if(value == undefined || value == "") return true;
	value = value.split(":");
	if(value.length != 2 || value[0].length == 0) return false;
	var port = Number(value[1]);
	return !isNaN(port) && port > 0 && port <= 65535;
};

validatePid = function(value) {
	if(value == undefined || value == "") return true;
	value = Number(value);
	return !isNaN(value) && value > 20 && value <= 8191;
};

validatePnr = function(value) {
	if(value == undefined || value == "") return true;
	value = Number(value);
	return !isNaN(value) && value > 0 && value <= 65535;
};

validateBiss = function(value) {
	if(value == undefined || value == "") return true;
	return /^[0-9A-Fa-f]{16}$/.test(value);
};

validateUrl = function(value) {
	if(value == undefined || value == "") return true;
	return !!parseUrl(value);
};

validateHex = function(value) {
	if(value == undefined || value == "") return true;
	return value.length % 2 == 0 && /^[0-9A-Fa-f]*$/.test(value);
};

Array.prototype.indexOfID = function(id) {
	for(var i = 0; i < this.length; ++i) {
		if(this[i].id == id) return i;
	}
	return -1;
};

Array.prototype.uniq = function() {
	var i = 1;
	while(i < this.length) {
		if(this[i - 1] == this[i]) this.splice(i, 1);
		else ++i;
	}
};

Number.prototype.format = function(c, d, t) {
	var n = this,
		c = isNaN((c = Math.abs(c))) ? 2 : c,
		d = d == undefined ? " " : d,
		t = t == undefined ? "." : t,
		s = n < 0 ? "-" : "",
		i = parseInt((n = Math.abs(+n || 0).toFixed(c))) + "",
		j = (j = i.length) > 3 ? j % 3 : 0;
	return (
		s +
		(j ? i.substr(0, j) + d : "") +
		i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + d) +
		(c
			? t +
				Math.abs(n - i)
					.toFixed(c)
					.slice(2)
			: "")
	);
};

Number.prototype.toHex = function(p, u) {
	var n = this,
		p = p == undefined ? 2 : p,
		h = n.toString(16);
	if(u) h = h.toUpperCase();
	while(h.length < p) h = "0" + h;
	return "0x" + h;
};

function ip2num(x) {
	if(!x) return 0;
	x = x.split(".");
	if(x.length != 4) return 0;
	return ((((((+x[0]) * 256) + (+x[1])) * 256) + (+x[2])) * 256) + (+x[3]);
}

parseUrlFormat = {};

parseUrlFormat["udp"] = function(r) {
	var b = r.addr.indexOf("/");
	if(b != -1) r.addr = r.addr.substring(0, b);
	b = r.addr.indexOf("@");
	if(b != -1) {
		if(b > 0) r.localaddr = r.addr.substring(0, b);
		r.addr = r.addr.substring(b + 1);
	}
	b = r.addr.indexOf(":");
	if(b != -1) {
		r.port = Number(r.addr.substring(b + 1));
		if(isNaN(r.port) || r.port < 1 || r.port > 65535) return false;
		r.addr = r.addr.substring(0, b);
	} else {
		r.port = 1234;
	}
	if(!r.addr.length) return false;
	var a = r.addr.split(".");
	if(a.length > 4) return false;
	while(a.length) {
		var o = Number(a.shift());
		if(isNaN(o) || o < 0 || o > 255) return false;
	}
	return true;
};

parseUrlFormat["rtp"] = parseUrlFormat["udp"];

parseUrlFormat["http"] = function(r) {
	var b = r.addr.indexOf("/");
	if(b != -1) {
		r.path = r.addr.substring(b);
		r.addr = r.addr.substring(0, b);
	} else {
		r.path = "/";
	}
	b = r.addr.indexOf("@");
	if(b != -1) {
		if(b > 0) {
			var a = r.addr.substring(0, b).split(":");
			if(a.length == 2) {
				r.login = a[0];
				r.password = a[1];
			}
		}
		r.addr = r.addr.substring(b + 1);
	}
	b = r.addr.indexOf(":");
	if(b != -1) {
		r.port = Number(r.addr.substring(b + 1));
		if(isNaN(r.port) || r.port < 1 || r.port > 65535) return false;
		r.host = r.addr.substring(0, b);
	} else {
		switch(r.format) {
			case "http":
				r.port = 80;
				break;
			case "https":
				r.port = 443;
				break;
			case "rtsp":
				r.port = 554;
				break;
			default:
				r.port = 80;
				break;
		}
		r.host = r.addr;
	}
	delete r.addr;
	if(!r.host.length) return false;
	return true;
};

parseUrlFormat["https"] = parseUrlFormat["http"];

parseUrlFormat["rtsp"] = parseUrlFormat["http"];

parseUrlFormat["np"] = parseUrlFormat["http"];

parseUrlFormat["file"] = function(r) {
	r.filename = r.addr;
	delete r.addr;
	return true;
};

parseUrlFormat["srt"] = function(r) {
	var b = r.addr.indexOf("/");
	if(b != -1) r.addr = r.addr.substring(0, b);
	var hasLocaladdr = false;
	b = r.addr.indexOf("@");
	if(b != -1) {
		r.localaddr = r.addr.substring(0, b);
		r.addr = r.addr.substring(b + 1);
		hasLocaladdr = true;
	}
	b = r.addr.indexOf(":");
	if(b != -1) {
		r.port = Number(r.addr.substring(b + 1));
		if(isNaN(r.port) || r.port < 1 || r.port > 65535) return false;
		r.addr = r.addr.substring(0, b);
	} else {
		return false;
	}
	if(hasLocaladdr) {
		if(r.addr.length != 0) return false;
	} else {
		if(r.addr.length == 0) return false;
	}
	return true;
};

function parseUrl(url) {
	if(!url) return null;
	var b = url.indexOf("://");
	if(b == -1 || url.length <= b + 3) return null;
	var r = {};
	r.format = url.substring(0, b);
	url = url.substring(b + 3);
	b = url.indexOf("#");
	if(b == -1) {
		r.addr = url;
	} else {
		r.addr = url.substring(0, b);
		url = url.substring(b + 1).split("&");
		for(var i = 0; i < url.length; ++i) {
			var o = url[i].split("="),
				k = o[0],
				v = o.length == 2 ? o[1] : true;
			r[k] = v;
		}
	}
	if(parseUrlFormat.hasOwnProperty(r.format) && !parseUrlFormat[r.format](r)) return null;
	return r;
}

makeUrlFormat = {};

makeUrlFormat["udp"] = function(d) {
	if(d.localaddr) {
		d.addr = d.localaddr + "@" + d.addr;
		delete d.localaddr;
	}
	if(d.port) {
		d.addr += ":" + d.port;
		delete d.port;
	}
};

makeUrlFormat["rtp"] = makeUrlFormat["udp"];

makeUrlFormat["srt"] = function(d) {
	if(d.localaddr != undefined) {
		d.addr = d.localaddr + "@";
		delete d.localaddr;
	}
	if(d.port) {
		d.addr += ":" + d.port;
		delete d.port;
	}
};

makeUrlFormat["http"] = function(d) {
	d.addr = "";
	if(d.login) {
		d.addr += d.login;
		delete d.login;
		if(d.password) {
			d.addr += ":" + d.password;
			delete d.password;
		}
		d.addr += "@";
	}
	if(d.host) {
		d.addr += d.host != "0.0.0.0" ? d.host : "0";
		delete d.host;
	}
	if(d.port) {
		d.addr += ":" + d.port;
		delete d.port;
	}
	if(d.path) {
		d.addr += d.path;
		delete d.path;
	}
};

makeUrlFormat["https"] = makeUrlFormat["http"];

makeUrlFormat["rtsp"] = makeUrlFormat["http"];

makeUrlFormat["np"] = makeUrlFormat["http"];

makeUrlFormat["file"] = function(d) {
	d.addr = d.filename;
	delete d.filename;
};

function makeUrl(data) {
	var d = $.clone(data);
	if(makeUrlFormat.hasOwnProperty(d.format)) makeUrlFormat[d.format](d);
	var r = d.format + "://" + (d.addr || "");
	delete d.format;
	delete d.addr;
	var o = [];
	for(k in d) {
		var v = d[k];
		if(!v) {
			continue;
		} else if(v === true) {
			o.push(k);
		} else {
			o.push(k + "=" + v);
		}
	}
	if(o.length) r += "#" + o.join("&");
	return r;
}

app.renderInit = function() {
	var menu = $.element().addClass("main-menu fixed");
	var renderMenu = function(list) {
		$.forEach(list, function(item) {
			menu.addChild(
				$.element
					.a(item.link || "#", item.label)
					.addClass(item.hide ? "hide" : null)
					.on("click", function(event) {
						if(item.click) {
							event.preventDefault();
							item.click(event);
						}
					})
			);
		});
	};
	var renderSearch = function() {
		var s = !app.module.search
			? $.element()
			: $.element
				.input("Click or press ‘S’ to search…")
				.addAttr("autocomplete", "off")
				.dataBind("search")
				.on("input", function() {
					app.search(this.value);
				})
				.on("keydown", function(event) {
					if(event.keyCode == 27) {
						this.value = "";
						app.search("");
						this.blur();
					}
				});
		s.addAttr("id", "search-bar").addClass("search");
		menu.addChild(s);
	};
	renderMenu(app.menu);
	renderMenu([{
		link: "https://help.cesbo.com?utm_source=astra",
		label: "Help",
	}])
	renderSearch();
	renderMenu(app.module.menu);
	$.body.addChild(menu);
	var content = $.element().addClass("main-content");
	$.body.addChild(content);
	return content;
};

function Form(scope, parent) {
	var form = $.element("form")
		.addClass("form")
		.addAttr("novalidate")
		.addAttr("autocomplete", "off")
		.on("keydown", function(event) {
			if(event.which == 13) {
				switch(event.target.tagName) {
					case "TEXTAREA":
					case "BUTTON":
						break;
					default:
						event.preventDefault();
						break;
				}
			}
		});
	this.node = form;
	this.scope = scope;
	if(parent) parent.addChild(form);

	this.loading = function() {
		var x = $.element().addClass("loading");
		for(var i = 0; i < 4; ++i) x.addChild($.element().addClass("bullet"));
		form.addChild(x);
		return x;
	};

	this.group = function() {
		var g = $.element().addClass("form-group");
		form.addChild(g);
		return g;
	};

	this.header = function(title, action, click) {
		var g = $.element()
			.addClass("form-group-header")
			.addChild(title || "");
		if(action && click) {
			g.addChild(
				$.element
					.a("#", action)
					.addClass("form-group-action")
					.on("click", function(event) {
						event.preventDefault();
						click();
					})
			);
		}
		form.addChild(g);
		return g;
	};

	this.hr = function() {
		var x = $.element("hr");
		form.addChild(x);
		return x;
	};

	this.tab = function(tabId, options) {
		var g = this.group(),
			c = scope.get(tabId),
			l = $.element().addClass("tab");
		if(c == undefined) c = options[0].id;
		$.forEach(options, function(v) {
			l.addChild(
				c == v.id
					? $.element("span").setText(v.label)
					: $.element.a(v.link || "#", v.label).on("click", function(event) {
						event.preventDefault();
						scope.set(tabId, v.id);
						scope.reset();
					})
			);
		});
		g.addChild(l);
		return l;
	};

	this.checkbox = function(title, bind) {
		var g = this.group();
		var x = $.element.checkbox(title || "");
		x.checkbox.dataBind(bind).addAttr("data-false", "undefined");
		x.checkbox.setDisabled = function(value) {
			var f = !!value ? "addAttr" : "removeAttr";
			var a = "disabled";
			x.checkbox[f](a);
			x[f](a);
			return x.checkbox;
		};
		x.checkbox.setDanger = function() {
			x.addClass("danger");
			return x.checkbox;
		};
		x.checkbox.awaiting = function(value) {
			x.checkbox.setDisabled(value);
			var f = !!value ? "addClass" : "removeClass";
			x[f]("awaiting");
		};
		g.addChild(x);
		return x.checkbox;
	};

	this.text = function(title, bind) {
		var x = $.element("textarea").dataBind(bind);
		var g = this.group().addClass("group-input").addChild(x);
		g.addChild($.element("span").addClass("label").setText(title));
		return x;
	};

	this.input = function(title, bind, placeholder) {
		var x = $.element.input().dataBind(bind);
		if(placeholder) x.addAttr("placeholder", placeholder);
		var g = this.group().addClass("group-input").addChild(x);
		g.addChild($.element("span").addClass("label").setText(title));
		x.on("mousewheel", function() {
			this.blur();
		});
		x.setRequired = function() {
			x.addAttr("required");
			x.addValidator(function(value) {
				return value != undefined && value != "";
			});
			return x;
		};
		x.setError = function(value) {
			if(value) {
				g.addClass("error");
				x.addClass("error");
			} else {
				g.removeClass("error");
				x.removeClass("error");
			}
		};
		x.addButton = function(button) {
			g.addChild(button);
			return x;
		};
		return x;
	};

	this.password = function(title, bind, placeholder) {
		var x = this.input(title, "$" + bind, placeholder);
		var h = function(p) {
			p = p || "";
			return new Array(p.length + 1).join("*");
		};
		scope.set("$" + bind, h(scope.get(bind)));
		x.on("focus", function() {
			scope.set("$" + bind, scope.get(bind) || "");
		}).on("blur", function() {
			scope.set(bind, scope.get("$" + bind));
			scope.set("$" + bind, h(scope.get(bind)));
		});
		return x;
	};

	this.number = function(title, bind, placeholder) {
		var x = this.input(title, bind, placeholder);
		return x;
	};

	this.choice = function(title, bind, options) {
		var x = $.element.select(options).dataBind(bind);
		var g = this.group().addClass("group-input").addChild(x);
		g.addChild($.element("span").addClass("label").setText(title));
		x.setRequired = function() {
			x.addAttr("required");
			x.addValidator(function(value) {
				return value != undefined && value != "";
			});
			return x;
		};
		x.setError = function(value) {
			if(value) {
				g.addClass("error");
				x.addClass("error");
			} else {
				g.removeClass("error");
				x.removeClass("error");
			}
		};
		return x;
	};

	this.hidden = function(bind) {
		var x = $.element("input").addAttr("type", "hidden").dataBind(bind);
		form.addChild(x);
		return x;
	};

	this.submit = function(btn) {
		var x = $.element().addClass("form-submit");
		form.addChild(x);
		return x;
	};
}

function Host(hostConfig, callback) {
	var self = this,
		host = hostConfig.host,
		protocol = hostConfig.https ? 'https:' : location.protocol,
		path = hostConfig.path ? '/' + hostConfig.path : '/',
		token = null;
	if(hostConfig.port) host += ":" + hostConfig.port;
	if(hostConfig.user) {
		token = hostConfig.user;
		if(hostConfig.pass) token += ":" + hostConfig.pass;
	}
	self.name = hostConfig.name || host;
	self.sysinfo = null;
	self.config = null;
	self.makeUid = function(type) {
		var arr = self.config[type];
		do {
			self.config.gid = self.config.gid + 1;
			var r = self.config.gid.toString(36);
			if(!arr || arr.indexOfID(r) == -1) return r;
		} while(true);
	};
	var ws, wsError;
	var connect = function() {
		ws = new WebSocket((protocol === "http:" ? "ws:" : "wss:") + "//" + host + path + "control/event/");
		ws.onopen = function() {
			ws.send(JSON.stringify({
				scope: "auth",
				auth: token,
			}));
		};
		ws.onclose = function() {
			app.removeHost(hostConfig);
			if(host == location.host) $.body.scope.destroy();
			wsError = $.err({
				title: self.name,
				text: "Connection closed. Retrying in {0}...",
				delay: 4,
			}).on("remove", function() {
				app.addHost(hostConfig, function() {
					if(host == location.host) app.route();
				});
			});
		};
		ws.onmessage = function(event) {
			var data;
			try {
				data = JSON.parse(event.data);
				if(!data.scope) throw "event scope not defined";
			} catch(e) {
				console.error(e);
				return;
			}
			app.emit(data.scope, {
				host: host,
				data: data,
			});
		};
	};
	var headers = {
		"Content-Type": "application/json",
	};
	self.request = function(data, onLoad, onError) {
		$.http({
			method: "POST",
			url: protocol + "//" + host + path + "control/",
			data: JSON.stringify(data),
			headers: headers,
		}, function(response) {
			if(onLoad) {
				response.data = JSON.parse(response.text);
				onLoad(response);
			}
		}, function(response) {
			if(onError) {
				onError(response);
			}
		});
	};
	self.restart = function() {
		self.request({
			cmd: "restart",
		});
	};
	self.upload = function(fn) {
		self.request({
			cmd: "upload",
			config: self.config,
		}, function() {
			if(fn) fn(true);
			self.restart();
		}, function() {
			$.err({
				title: self.name,
				text: "Upload failed",
			});
			if(fn) fn(false);
		});
	};
	var authForm = null;
	var authFormInit = function() {
		if(authForm) {
			authForm.setDisabled(false);
			return;
		}
		var u = $.element.input("Login");
		var p = $.element.input("Password", "password");
		var r = $.element.checkbox("Remember me");
		var s = $.element.button("Sign In").addAttr("type", "submit").addClass("submit");
		authForm = $.element("form")
			.addClass("auth")
			.addChild(u, p, r, s)
			.on("submit", function(event) {
				event.preventDefault();
				authForm.setDisabled(true);
				app.login = u.value;
				token = u.value + ":" + p.value;
				$.cookie.set("auth", r.checkbox.checked ? token : undefined);
				p.value = "";
				load();
			});
		authForm.setDisabled = function(value) {
			s.setDisabled(value);
		};
		$.body.addChild(authForm);
		u.focus();
	};
	var loadError = null;
	var load = function() {
		if(token) headers["Authorization"] = "Basic " + $.base64Encode(token);
		if(loadError) {
			loadError.remove();
			loadError = null;
		}
		self.request({
			cmd: "status",
		}, function(response) {
			var data = response.data;
			if(authForm) {
				authForm.remove();
				authForm = null;
			}
			if(data.net_list) {
				data.net_list.sort(function(a, b) {
					a.name.localeCompare(b.name);
				});
				var if_list = [];
				$.forEach(data.net_list, function(i) {
					let label = !i.ipv4 ? i.name : i.name + ': ' + i.ipv4[0];
					if_list.push({
						value: i.name,
						label,
					});
				});
				data.if_list = if_list;
				delete data.net_list;
			} else if(data.if_list) {
				data.if_list.sort();
				var if_list = [];
				$.forEach(data.if_list, function(i) {
					if_list.push({
						value: i,
					});
				});
				data.if_list = if_list;
			}
			if(data.observer) {
				SettingsModule.hide = true;
				app.observer = true;
			}
			self.sysinfo = data;
			self.request({
				cmd: "load",
			}, function(response) {
				var data = response.data;
				self.config = $.isObject(data) ? data : {};
				if(!self.config.gid) self.config.gid = 466560;
				connect();
				callback.call(self);
			}, function() {
				loadError = $.err({
					title: "Configuration file has wrong format",
					delay: -1,
				});
			});
		}, function(response) {
			if(response.status == 403) {
				var text = "Authentication failed.";
				if(location.host == host) {
					authFormInit();
					if(!token) return;
				} else {
					var idx = app.hosts[location.host].config.servers.indexOf(hostConfig);
					text += '<br/><a href="#/settings-servers/' + idx + '">Check streamer configuration</a>';
				}
				loadError = $.err({
					title: self.name,
					text: text,
					delay: -1,
				});
			} else {
				loadError = $.err({
					title: self.name,
					text: "Connection failed. Retrying in {0}...",
					delay: 10,
				}).on("remove", function() {
					loadError = null;
					if(load) load();
				});
			}
		});
	};
	load();
	self.destroy = function() {
		load = undefined;
		if(loadError) {
			loadError.remove();
			loadError = null;
		}
		if(wsError) {
			wsError.remove();
			wsError = null;
		}
		if(ws) {
			ws.onclose = null;
			if(ws.readyState == WebSocket.OPEN) ws.close();
			ws = null;
		}
	};
}

app.addHost = function(config, fn) {
	var host = config.host;
	if(config.port) host += ":" + config.port;
	app.hosts[host] = new Host(config, function() {
		if(fn) fn.call(this);
		$.forEach(app.modules, function(m) {
			if(m.addHost) m.addHost(host);
		});
	});
};

app.removeHost = function(config) {
	var host = config.host;
	if(config.port) host += ":" + config.port;
	if(app.hosts[host]) {
		$.forEach(app.modules, function(m) {
			if(m.removeHost) m.removeHost(host);
		});
		app.hosts[host].destroy();
		delete app.hosts[host];
	}
};

app.selectHost = function(link, id) {
	if(Object.keys(app.hosts).length == 1) {
		if(typeof(link) === "function") {
			link(location.host, id);
		} else {
			id = id ? "/" + id : "";
			$.route(link + "/" + location.host + id);
		}
		return;
	}

	var modal = $.modal().addClass("main-menu");

	if(typeof(link) === "function") {
		$.forEach(app.hosts, function(appHost, hostId) {
			if(appHost.config) {
				modal.addChild(
					$.element.a("#", appHost.name)
						.on("click", function(event) {
							event.preventDefault();
							modal.remove()
							link(hostId, id);
						})
				);
			}
		});
	} else {
		id = id ? "/" + id : "";
		$.forEach(app.hosts, function(appHost, hostId) {
			if(appHost.config) {
				modal.addChild(
					$.element
						.a(link + "/" + hostId + id, appHost.name)
						.on("click", function() {
							modal.remove();
						})
				);
			}
		});
	}
	modal.addChild($.element("hr"));
	modal.addChild($.element.a("#", "Cancel").addClass("text-center").on("click", function(event) {
		event.preventDefault();
		modal.remove();
	}));
};

function Scan(hostId, config, fn) {
	var scanId = null,
		scanTimer = null,
		tsid = -1,
		scanData = [],
		psiCache = [],
		appHost = app.hosts[hostId],
		changed = false;
	var getScanItem = function(pnr) {
		var i, x;
		for(i = 0; i < scanData.length; ++i) {
			x = scanData[i];
			if(x.pnr == pnr) return x;
		}
		x = {
			pnr: pnr,
			name: "Unknown",
		};
		scanData.insertSorted(x, function(a, b) {
			return a.pnr - b.pnr;
		});
		return x;
	};
	var scanCheckPsi = function(psi) {
		if(tsid == -1 && psi.psi != "pat") {
			psiCache.push(psi);
		} else if(scanCheckPsi[psi.psi] != undefined) {
			scanCheckPsi[psi.psi](psi);
		}
	};
	scanCheckPsi.pat = function(pat) {
		tsid = pat.tsid;
		$.forEach(psiCache, scanCheckPsi);
		psiCache = [];
		changed = true;
	};
	scanCheckPsi.nit = function(nit) {
		var data = getScanItem(0);
		$.forEach(nit.descriptors, function(d) {
			if(d.type_id == 64) data.name = d.network_name;
		});
		$.forEach(nit.streams, function(s) {
			if(s.tsid != tsid) return;
			$.forEach(s.descriptors, function(d) {
				switch(d.type_id) {
					case 67:
						data.system = d;
						data.name = (d.s2 ? "DVB-S2" : "DVB-S") + " : " + data.name;
						break;
					case 68:
						data.system = d;
						data.name = "DVB-C : " + data.name;
						break;
					case 90:
						data.system = d;
						data.name = "DVB-T : " + data.name;
						break;
				}
			});
		});
		changed = true;
	};
	scanCheckPsi.pmt = function(pmt) {
		var data = getScanItem(pmt.pnr);
		data.streams = [];
		data.cas = [];
		$.forEach(pmt.descriptors, function(d) {
			if(d.type_id == 9) data.cas.push(d.caid.toHex(4));
		});
		$.forEach(pmt.streams, function(x) {
			if(["VIDEO", "AUDIO"].indexOf(x.type_name) == -1) return;
			var r = x.type_name.charAt(0) + "PID:" + x.pid;
			var e = null;
			var l = null;
			if(x.type_id == 27) e = "MPEG-4";
			$.forEach(x.descriptors, function(d) {
				switch(d.type_id) {
					case 9:
						data.cas.push(d.caid.toHex(4));
						break;
					case 10:
						l = d.lang;
						break;
					case 106:
						e = "AC-3";
						break;
				}
			});
			if(e) r = r + " " + e;
			if(l) r = r + " " + l;
			data.streams.push(r);
		});
		data.cas.sort();
		data.cas.uniq();
		changed = true;
	};
	scanCheckPsi.sdt = function(sdt) {
		$.forEach(sdt.services, function(x) {
			var data = getScanItem(x.sid);
			$.forEach(x.descriptors, function(d) {
				if(d.type_id == 72) {
					data.name = d.service_name || "Unknown";
					data.provider = d.service_provider;
				}
			});
		});
		changed = true;
	};
	var scanCheck = function() {
		appHost.request({
			cmd: "scan-check",
			id: scanId,
		}, function(response) {
			var data = response.data;
			if(scanData) {
				$.forEach(data.scan, scanCheckPsi);
				if(changed) {
					fn(scanData);
					changed = false;
				}
			}
		});
	};
	appHost.request({
		cmd: "scan-init",
		scan: config,
	}, function(response) {
		if(!scanData) return;
		var data = response.data;
		scanId = data.id;
		scanTimer = setInterval(scanCheck, 2e3);
	}, function() {
		$.err({
			title: appHost.name,
			text: "Failed to scan stream",
		});
	});
	this.destroy = function() {
		if(scanTimer) {
			clearInterval(scanTimer);
			scanTimer = null;
		}
		if(scanData) scanData = null;
		if(scanId) {
			appHost.request({
				cmd: "scan-kill",
				id: scanId,
			}, function() {
				scanId = null;
			});
		}
	};
}

Element.prototype.dataRender = function(fn) {
	console.warn("Deprecated method: dataRender()");
	this.dataset.render = fn;
	return this;
};

Element.prototype._bindScope = Element.prototype.bindScope;

Element.prototype.bindScope = function() {
	var args = arguments,
		self = this;
	if(args.length == 1) {
		console.warn("Deprecated method: bindScope()");
		var render,
			scope = args[0];
		if(self == $.body) {
			if(!window.renderContent) throw "render target not found";
			render = function() {
				var object = app.renderInit();
				window.renderContent.call(self, object);
			};
		} else {
			var dst = window,
				el = self.querySelector("*[data-render]"),
				key = el.dataset.render.split(".");
			while(key.length > 0 && !!dst) dst = dst[key.shift()];
			if(!dst) throw "render callback not found [" + el.dataset.render + "]";
			render = function() {
				dst.call(self, self);
			};
		}
		args = [render, scope].concat(Array.prototype.slice.call(args, 1));
	}
	Element.prototype._bindScope.apply(self, args);
	return self;
};

app.setTitle = function(value) {
	var b = "Astra Control Panel";
	document.title = !!value ? value + " - " + b : b;
};

app.setTheme = function(value) {
	if($.html.theme) $.html.removeClass($.html.theme);
	if(value) $.html.addClass(value);
	$.html.theme = value;
};

app.menu.push = function(item) {
	this.insertSorted(item, function(a, b) {
		var ao = a.order != undefined ? a.order : 1e3;
		var bo = b.order != undefined ? b.order : 1e3;
		return ao - bo;
	});
};

app.settings.push = function(item) {
	this.insertSorted(item, function(a, b) {
		var ao = a.order != undefined ? a.order : 1e3;
		var bo = b.order != undefined ? b.order : 1e3;
		return ao > bo ? 1 : -1;
	});
};

app.route = function() {
	var route = location.hash.match(/^(#\/[a-z-]*)\/*/);
	app.module = null;
	if(route) {
		for(var i = 0; i < app.modules.length; ++i) {
			app.module = app.modules[i];
			if(app.module.link == route[1]) break;
			app.module = null;
		}
	}
	if(!app.module) {
		$.route(app.modules[0].link);
	} else {
		if(app.search) app.search("");
		app.search = $.nop;
		app.module.init();
	}
};

app.eventBind = {};

app.on = function(event, fn) {
	var eb = app.eventBind[event];
	if(!eb) app.eventBind[event] = eb = [];
	eb.push(fn);
};

app.off = function(event, fn) {
	var eb = app.eventBind[event];
	if(eb) {
		eb.splice(eb.indexOf(fn), 1);
		if(!eb.length) delete app.eventBind[event];
	}
};

app.emit = function(event) {
	var eb = app.eventBind[event];
	if(eb) {
		for(var i = 0; i < eb.length; i++) {
			eb[i].apply(this, Array.prototype.slice.call(arguments, 1));
		}
	}
};

app.scope = {
	on: function(event, fn) {
		console.log("Deprecated Web-API for event:" + event);
		app.on(event, fn);
	},
	off: function(event, fn) {
		app.off(event, fn);
	},
};

$.route = function(l) {
	location.href = l;
};

$(function() {
	window.addEventListener("hashchange", app.route);
	var globalKeyHandler = function(e) {
		if(e.altKey || e.ctrlKey || e.metaKey || e.shiftKey) return;
		if(document.activeElement == document.body && app.module.search) {
			if(e.keyCode == 83) {
				e.preventDefault();
				window.scrollTo(0, 0);
				document.getElementById("search-bar").focus();
			}
			return;
		}
	};

	document.on("keydown", globalKeyHandler);

	app.on("auth", function(event) {
		var host = event.host,
			data = event.data,
			appHost = app.hosts[host];
		appHost.wsid = data.id;
	});

	var token = $.cookie.get("auth");
	if(token) app.login = token.split(":")[0];
	else app.login = "admin";

	app.addHost({
		host: location.hostname,
		port: location.port,
		path: location.pathname.substring(1),
		user: token,
	}, function() {
		let interface_cfg = {};
		if(app.login in this.config.users) {
			interface_cfg = this.config.users[app.login].interface || {};
		}

		if(interface_cfg && interface_cfg.theme) {
			app.setTheme(interface_cfg.theme);
		} else if(window.matchMedia("(prefers-color-scheme: dark)").matches) {
			app.setTheme("dark");
		}
		if(interface_cfg) {
			MainModule.view = interface_cfg;
			if(interface_cfg.title) app.setTitle(interface_cfg.title);
		}

		$.forEach(app.modules, function(m) {
			if(m.run) m.run();
		});
		app.route();
		$.forEach(this.config.servers, function(s) {
			if(s.type == "streamer" && s.enable != false) app.addHost(s);
		});
	});
});

/* dashboard.js */

(function() {
"use strict";

window.MainModule = {
	label: "Dashboard",
	link: "#/",
	order: 0,
	search: true,
	node: $.element(),
	dvbDevList: {},
	adapters: {},
	streams: {},
	view: {},
	menu: [{
		label: "New Adapter",
		hide: app.observer == true,
		click: function() {
			app.selectHost(AdaptersModule.modal, "-")
		},
	}, {
		label: "New Stream",
		hide: app.observer == true,
		click: function() {
			app.selectHost(StreamsModule.modal, "-")
		},
	}, {
		label: "View",
		click: function() {
			SettingsInterfaceModule.modal()
		},
	}]
};

MainModule.run = function() {
	app.on("set-adapter", function(event) {
		var host = event.host,
			data = event.data,
			appHost = app.hosts[host];
		if(data.gid) appHost.config.gid = data.gid;
		var al = appHost.config.dvb_tune;
		if(data.adapter.remove) {
			var idx = !al ? -1 : al.indexOfID(data.adapter.id);
			if(!data.adapter.up) {
				$.msg({
					title: 'Adapter "{0}" removed'.format(al[idx].name),
				});
			}
			MainModule.adapters[host + "/" + data.adapter.id].remove();
			al.splice(idx, 1);
			if(!al.length) delete appHost.config.dvb_tune;
		} else {
			if(!al) appHost.config.dvb_tune = al = [];
			al.push(data.adapter);
			renderAdapter(host, data.adapter);
			$.msg({
				title: 'Adapter "{0}" saved'.format(data.adapter.name),
			});
		}
	});
	app.on("adapter_event", function(event) {
		var data = event.data,
			node = MainModule.adapters[event.host + "/" + data.dvb_id];
		if(!node) return;
		if(data.satip || data.virtual) {
			data.connect = data.status == 8;
		} else {
			if(data.signal > 100) data.signal = Math.floor((data.signal * 99) / 65535);
			if(data.snr > 100) data.snr = Math.floor((data.snr * 99) / 65535);
			data.ber_value = data.ber > 99 ? "99+" : data.ber;
			data.unc_value = data.unc > 99 ? "99+" : data.unc;
		}
		node.setStatus(data);
	});
	app.on("set-stream", function(event) {
		var host = event.host,
			appHost = app.hosts[host],
			data = event.data;
		if(data.gid) appHost.config.gid = data.gid;
		var sl = appHost.config.make_stream;
		if(data.stream.remove) {
			var idx = !sl ? -1 : sl.indexOfID(data.stream.id);
			if(!data.stream.up) {
				$.msg({
					title: 'Stream "{0}" removed'.format(sl[idx].name),
				});
			}
			MainModule.streams[host + "/" + data.stream.id].remove();
			sl.splice(idx, 1);
			if(!sl.length) delete appHost.config.make_stream;
		} else {
			if(!sl) appHost.config.make_stream = sl = [];
			sl.push(data.stream);
			renderStream(host, data.stream);
			$.msg({
				title: 'Stream "{0}" saved'.format(data.stream.name),
			});
		}
	});
	app.on("stream_event", function(event) {
		var data = event.data,
			node = MainModule.streams[event.host + "/" + data.channel_id];
		if(!node) return;
		node.lastEvent = new Date();
		if(!!data.input_id) node.$input[data.input_id - 1].lastEvent = node.lastEvent;
		node.setStatus(data);
	});
	app.on("stream_image", function(event) {
		var host = event.host,
			data = event.data,
			node = MainModule.streams[host + "/" + data.channel_id];
		if(!node) return;
		var i = new Image();
		i.onload = function() {
			node.$image
				.setStyle("background-image", "url('" + i.src + "')")
				.setStyle("display", "block");
		};
		i.src = data.src;
	});

	MainModule.refresh = setInterval(function() {
		var ct = new Date();
		$.forEach(MainModule.streams, function(s) {
			if(s.$config.type == "spts") {
				if(s.lastEvent && ct - s.lastEvent > 15e3) {
					s.reset();
				} else {
					$.forEach(s.$input, function(i) {
						if(i.lastEvent && ct - i.lastEvent > 15e3 && i.$onair != undefined) {
							i.className = "text";
							i.setText("Inactive");
							delete i.$onair;
						}
					});
				}
			}
		});
	}, 1e3);
};

MainModule.update = function() {
	var appHost = app.hosts[location.host];
	MainModule.view = {};
	if(app.login in appHost.config.users) {
		MainModule.view = appHost.config.users[app.login].interface || {};
	}

	$.forEach(MainModule.adapters, function(node) {
		node.remove();
	});
	$.forEach(MainModule.streams, function(node) {
		node.remove();
	});
	$.forEach(app.hosts, function(appHost, host) {
		$.forEach(appHost.config.dvb_tune, function(c) {
			renderAdapter(host, c);
		});
		$.forEach(appHost.config.make_stream, function(c) {
			renderStream(host, c);
		});
	});
};

MainModule.dvbLevel = function(t) {
	var x = $.element("div").addClass("dvb-status row monospace");
	var x1 = $.element("div").addClass("text").setText(t);
	var x2 = $.element("div").addClass("progress signal-level col-expand");
	var b = $.element("div").addClass("progress-level");
	var o = $.element("div").addClass("progress-overlay");
	x2.addChild(b, o);
	var x3 = $.element("div").addClass("text");
	x.addChild(x1, x2, x3);
	x.setLevel = function(v) {
		v = v + "%";
		b.style.width = v;
		x3.setText((" " + v).slice(-3));
	};
	x.setLevel(0);
	return x;
};

var cmpStack = function(a, b) {
	return b.$name ? a.$name.localeCompare(b.$name) : 1;
};

var cmpItems = {};

cmpItems["default"] = function(a, b) {
	return a.$config.name.localeCompare(b.$config.name);
};

cmpItems["lcn"] = function(a, b) {
	if(a.$type !== b.$type) return a.$type === "adapter" ? -1 : 1;
	if(a.$config.lcn === undefined) return 1;
	if(b.$config.lcn === undefined) return -1;
	return a.$config.lcn - b.$config.lcn;
};

var renderStack = function(name) {
	var node = $.forEach(MainModule.node.childNodes, function(i) {
		if(i.$name == name) return i;
	});
	if(!node) {
		node = $.element().addClass("card-stack");
		node.$name = name;
		if(name) node.addAttr("data-header", name);
		if(MainModule.view.hide_disabled) node.addClass("card-hide-disabled");
		if(MainModule.view.hide_inactive) node.addClass("card-hide-inactive");
		if(MainModule.view.hide_wo_error) node.addClass("card-hide-wo-error");
		if(MainModule.view.order) node.addClass("card-order-" + MainModule.view.order);
		MainModule.node.insertSorted(node, cmpStack);
	}
	return node;
};

var getItemGroup = function(item) {
	switch(MainModule.view.arrange) {
		case undefined:
			return "";
		case "$type":
			return item.$type + "s";
		case "$host":
			return app.hosts[item.$host].name;
		case "$dvb":
			return item.$type == "adapter"
				? item.$config.name
				: $.forEach(item.$config.input, function(i) {
					i = i.match(/^dvb:\/\/([^#]*)/);
					if(i) {
						i = item.$host + "/" + i[1];
						i = MainModule.adapters[i];
						if(i) return i.$config.name;
					}
				}) || "";
		default:
			return (item.$config.groups || {})[MainModule.view.arrange] || "";
	}
};

var renderAdapter = function(host, config) {
	var appHost = app.hosts[host];

	var node = $.element("a")
		.addClass("card card-adapter")
		.addAttr("href", "#/adapter/" + host + "/" + encodeURIComponent(config.id))
		.on("click", function(event) {
			event.preventDefault();
			AdaptersModule.modal(host, config.id);
		});

	node.$type = "adapter";
	node.$host = host;
	node.$config = config;
	node.$lock = 0;
	node.addClass("card-" + config.enable.toString() + "-" + node.$lock);
	node.addChild(
		$.element("div")
			.addClass("card-name")
			.setText(config.name)
			.addAttr("title", config.name)
	);

	var restartAdapter = function() {
		appHost.request({
			cmd: "restart-adapter",
			id: config.id,
		}, $.nop, function() {
			$.err({
				title: "Failed to restart adapter",
			});
		});
	};

	var setAdapter = function(a) {
		appHost.request({
			cmd: "set-adapter",
			id: config.id,
			adapter: a,
		}, $.nop, function() {
			$.err({
				title: "Failed to save adapter",
			});
		});
	};

	const menuItems = [{
		label: "Restart",
		click() {
			restartAdapter();
		},
	}, {
		label: (config.enable == false) ? "Enable" : "Disable",
		click() {
			let a = $.clone(config);
			a.enable = !a.enable;
			setAdapter(a);
		},
	}, {
		label: "---",
	}, {
		label: "Remove",
		style: "text-alert",
		click() {
			const text = "Remove adapter \"{0}\" and all related streams?".format(config.name);
			if(confirm(text)) {
				setAdapter({
					remove: true,
				});
			}
		},
	}];

	node.addChild(
		$.dropdown(
			$.element("i").addClass("button icon icon-more small"),
			menuItems
		)
			.addClass("card-action")
	);

	if(config.virtual == "ci" || config.virtual == "mpts") {
		var inode = $.element("span")
			.addClass("text")
			.setText("Inactive");
		var iwrap = $.element("div")
			.addClass("card-status")
			.addAttr("title", "CI " + config.stream + "/" + config.adapter)
			.addChild(inode);
		node.addChild(iwrap);
		node.setStatus = function(s) {
			if(!config.enable) return;
			var c = "text",
				t = "" + s.bitrate + "Kbit/s";
			if(s.on_air) {
				c += " onair";
			} else {
				c += " error";
			}
			inode.setText(t);
			if(inode.className != c) inode.className = c;
			var onair = s.on_air ? 2 : 0;
			if(node.$onair != onair) {
				node.removeClass("card-true-" + node.$onair);
				node.$onair = onair;
				node.addClass("card-true-" + node.$onair);
			}
		};
		node.setStatus({
			connect: false,
			bitrate: 0,
		});
	} else if(config.virtual == "satip" || config.satip) {
		var inode = $.element("span")
			.addClass("text")
			.setText("Inactive");
		var iwrap = $.element("div")
			.addClass("card-status")
			.addAttr("title", "SAT>IP " + config.satip + "/" + config.adapter)
			.addChild(inode);
		node.addChild(iwrap);
		node.setStatus = function(s) {
			if(!config.enable) return;
			var c = "text",
				t = "" + s.bitrate + "Kbit/s";
			if(s.connect) {
				c += " onair";
			} else {
				c += " error";
			}
			inode.setText(t);
			if(inode.className != c) inode.className = c;
			var onair = s.connect ? 2 : 0;
			if(node.$onair != onair) {
				node.removeClass("card-true-" + node.$onair);
				node.$onair = onair;
				node.addClass("card-true-" + node.$onair);
			}
		};
		node.setStatus({
			connect: false,
			bitrate: 0,
		});
	} else {
		var sS = MainModule.dvbLevel("S").addClass("card-status");
		var sQ = MainModule.dvbLevel("Q").addClass("card-status");
		node.addChild(sS, sQ);
		var eT = $.element("span").addClass("text");
		node.addChild($.element("div").addClass("card-status monospace").addChild(eT));
		node.setStatus = function(s) {
			sS.setLevel(s.signal);
			sQ.setLevel(s.snr);
			eT.setText("ber:" + s.ber_value + " unc:" + s.unc_value);
			var l = s.status & 16 ? 2 : 0;
			if(l != node.$lock) {
				node.removeClass("card-true-" + node.$lock);
				node.$lock = l;
				node.addClass("card-true-" + node.$lock);
			}
		};
		node.setStatus({
			lock: false,
			signal: 0,
			snr: 0,
			ber_value: 0,
			unc_value: 0,
		});
	}
	node.$stack = renderStack(getItemGroup(node));
	node.$stack.insertSorted(node, (!MainModule.view.order || !cmpItems[MainModule.view.order]) ? cmpItems["default"] : cmpItems[MainModule.view.order]);
	node.remove = function() {
		var stack = this.$stack;
		delete this.$stack;
		Element.prototype.remove.call(this);
		delete MainModule.adapters[host + "/" + config.id];
		if(!stack.childNodes.length) stack.remove();
	};
	MainModule.adapters[host + "/" + config.id] = node;
};

var renderStream = function(host, config) {
	var appHost = app.hosts[host];

	var node = $.element("a")
		.addClass("card card-stream", "stream-" + (config.type || "unknown"))
		.addAttr("href", "#/stream/" + host + "/" + encodeURIComponent(config.id))
		.on("click", function(event) {
			event.preventDefault();
			StreamsModule.modal(host, config.id);
		});

	var onairDef;
	if(!config.enable) {
		onairDef = 0;
	} else if(config.type == "mpts") {
		onairDef = 2;
	} else {
		onairDef = 3;
	}
	node.$onair = onairDef;
	node.addClass("card-" + config.enable.toString() + "-" + node.$onair);
	node.$type = "stream";
	node.$host = host;
	node.$config = config;
	node.$input = [];
	node.$total = null;
	node.addChild(
		$.element("div")
			.addClass("card-name")
			.setText(config.name)
			.addAttr("title", config.name || "-")
	);

	const menuItems = [{
		label: "Analyze",
		disable: !config.enable,
		click() {
			StreamsModule.startAnalyze(host, config.id);
		},
	}, {
		label: "Toggle Input",
		hide: (!config.enable || (config.backup_type != "passive" && config.backup_type != "disable")),
		click() {
			appHost.request({
				cmd: "set-stream-input",
				id: config.id,
			}, $.nop, function() {
				$.err({
					title: "Failed to toggle input"
				});
			});
		},
	}, {
		label: (!config.enable) ? "Enable" : "Disable",
		click() {
			let a = $.clone(config);
			a.enable = !a.enable;
			appHost.request({
				cmd: "set-stream",
				id: config.id,
				stream: a,
			}, $.nop, function() {
				$.err({
					title: "Failed to save stream",
				});
			});
		},
	}, {
		label: "---",
	}, {
		label: "Remove",
		style: "text-alert",
		click() {
			const text = "Remove stream \"{0}\" ?".format(config.name);
			if(confirm(text)) {
				appHost.request({
					cmd: "set-stream",
					id: config.id,
					stream: {
						remove: true,
					},
				}, $.nop, function() {
					$.err({
						title: "Failed to remove stream"
					});
				});
			}
		},
	}];

	node.addChild(
		$.dropdown(
			$.element("i").addClass("button icon icon-more small"),
			menuItems
		)
			.addClass("card-action")
	);

	node.$image = $.element("div").addClass("card-image");
	node.addChild(node.$image);
	$.forEach(config.input, function(v) {
		var inode = $.element("span").addClass("text").setText("Inactive");

		let [u, h] = v.split("#");
		let name = u;
		const opts = new URLSearchParams(h);
		if(opts.has("name")) name = opts.get("name");

		var iwrap = $.element("div")
			.addClass("card-status")
			.addAttr("title", name)
			.addChild(inode);

		node.addChild(iwrap);
		node.$input.push(inode);
	});
	if(config.type == "mpts") {
		var tc = $.element("span").addClass("text").setText("Inactive");
		var tr = $.element("div").addClass("card-status card-footer").addChild(tc);
		node.addChild(tr);
		node.$total = tc;
		var sm = {};
		$.forEach(config.sdt, function(v) {
			sm[v.pnr] = v.name;
		});
		$.forEach(config.input, function(v, i) {
			var ac = parseUrl(v);
			if(!ac) return;
			var pnr = ac.set_pnr || ac.pnr || 0;
			if(pnr != 0) {
				var n = sm[pnr];
				if(n) node.$input[i].addAttr("data-name", "[" + n + "]");
			}
		});
	} else {
		if(config.enable && appHost.config.settings?.http_play_screenshots) {
			const basePath = appHost.config.settings.http_play_playlist_name || "playlist"
			node.$image
				.setStyle("background-image", `url('/${ basePath }/screenshots/${ config.id }.png')`)
				.setStyle("display", "block");
		}
	}

	node.$stack = renderStack(getItemGroup(node));
	node.$stack.insertSorted(node, (!MainModule.view.order || !cmpItems[MainModule.view.order]) ? cmpItems["default"] : cmpItems[MainModule.view.order]);
	node.reset = function() {
		$.forEach(node.$input, function(i) {
			i.className = "text";
			i.setText("Inactive");
			delete i.$onair;
		});
		node.removeClass("card-true-" + node.$onair);
		node.$onair = 3;
		node.addClass("card-true-" + node.$onair);
	};
	node.setStatus = function(s) {
		var c = "text",
			t = "" + s.bitrate + "Kbit/s",
			inode = !!s.input_id ? node.$input[s.input_id - 1] : node.$total;
		if(s.onair) {
			c += " onair";
		} else if(s.scrambled) {
			t += " Scrambled";
			c += " scrambled";
		} else {
			if(s.pes_error > 0) t += " PES:" + (s.pes_error > 99 ? "99+" : s.pes_error);
			c += " error";
		}
		if(s.cc_error > 0) {
			t += " CC:" + (s.cc_error > 99 ? "99+" : s.cc_error);
			c += " cc";
		}
		inode.setText(t);
		if(inode.className != c) inode.className = c;
		if(onairDef == 2) return;
		if(inode.$onair == s.onair) return;
		inode.$onair = s.onair;
		var onair = onairDef;
		var inodeReset = function(i) {
			var x = node.$input[i];
			if(x.$onair != undefined) {
				x.className = "text";
				x.setText("Inactive");
				delete x.$onair;
			}
		};
		if(config.backup_type == "passive" || config.backup_type == "disable") {
			if(s.onair) {
				onair = 2;
			}
			for(var i = 0, l = s.input_id - 1; i < l; i++) inodeReset(i);
			for(var i = s.input_id, l = node.$input.length; i < l; i++) inodeReset(i);
		} else {
			if(s.onair) {
				if(s.input_id == 1) onair = 2;
				else if(onair == 0) onair = 1;
				for(var i = s.input_id, l = node.$input.length; i < l; i++) inodeReset(i);
			} else {
				onair = 0;
			}
		}
		if(node.$onair != onair) {
			node.removeClass("card-true-" + node.$onair);
			node.$onair = onair;
			node.addClass("card-true-" + node.$onair);
		}
	};
	node.remove = function() {
		var stack = this.$stack;
		delete this.$stack;
		Element.prototype.remove.call(this);
		delete MainModule.streams[host + "/" + config.id];
		if(!stack.childNodes.length) stack.remove();
	};
	MainModule.streams[host + "/" + config.id] = node;
};

var initDvbDevList = function(hostId) {
	var appHost = app.hosts[hostId],
		gAvail = { group: "Available", items: [] },
		gTaken = { group: "Taken", items: [] },
		gError = { group: "Error", items: [] },
		dvbDevList = [{
			value: "",
			label: "",
		}, gAvail, gTaken, gError],
		dl = appHost.sysinfo.dvb_list;
	if(dl) {
		dl.sort(function(a, b) {
			if(a.error === b.error) {
				if(a.busy === b.busy) {
					if(a.adapter === b.adapter) {
						if(a.device === b.device) {
							return 0;
						}
						return a.device < b.device ? -1 : 1;
					}
					return a.adapter < b.adapter ? -1 : 1;
				}
				return a.busy != true ? -1 : 1;
			}
			return a.error == undefined ? -1 : 1;
		});
	}
	$.forEach(dl, function(a, i) {
		a.value = String(i);
		var d = a.adapter + "." + a.device + " : ";
		if(a.error) {
			a.label = d + a.error;
			gError.items.push(a);
		} else if(a.busy) {
			a.label = d + a.frontend;
			gTaken.items.push(a);
		} else {
			a.label = d + a.frontend;
			gAvail.items.push(a);
		}
	});
	return dvbDevList;
};

MainModule.addHost = function(host) {
	var appHost = app.hosts[host];
	if(!appHost.config) return;
	MainModule.dvbDevList[host] = initDvbDevList(host);
	$.forEach(appHost.config.dvb_tune, function(c) {
		renderAdapter(host, c);
	});
	$.forEach(appHost.config.make_stream, function(c) {
		renderStream(host, c);
	});
};

MainModule.removeHost = function(host) {
	$.forEach(MainModule.adapters, function(node, i) {
		if(node.$host == host) node.remove();
	});
	$.forEach(MainModule.streams, function(node, i) {
		if(node.$host == host) node.remove();
	});
	delete MainModule.dvbDevList[host];
};

var renderCards = function() {
	var self = this,
		appHost = app.hosts[location.host],
		object = app.renderInit();
	object.addChild(MainModule.node);
	app.search = function(value) {
		value = value.toLowerCase();
		var searchName = function(val, item) {
			return item.$config.name.toLowerCase().indexOf(val) != -1;
		};
		var searchInput = function(val, item) {
			var input = item.$config.input;
			if(input)
				for(var i = 0; i < input.length; i++) {
					if(input[i].split("#")[0].indexOf(val) != -1) return true;
				}
			return false;
		};
		var searchOutput = function(val, item) {
			var output = item.$config.output;
			if(output)
				for(var i = 0; i < output.length; i++) {
					if(output[i].split("#")[0].indexOf(val) != -1) return true;
				}
			return false;
		};
		var searchAll = function(val, item) {
			return searchName(val, item) || searchInput(val, item) || searchOutput(val, item);
		};
		$.forEach(MainModule.node.childNodes, function(stack) {
			stack.removeClass("hide");
			var sh = true;
			$.forEach(stack.childNodes, function(item) {
				if(!item.removeClass) console.log(item);
				item.removeClass("hide");
				if(!!value && !searchAll(value, item)) item.addClass("hide");
				else sh = false;
			});
			if(sh) stack.addClass("hide");
		});
	};
	var info = appHost.sysinfo;
	var text = "Astra " + info.version + " [" + info.commit + "]";
	$.body.addChild($.element().addClass("version monospace").setText(text));

	var firstrun = false;
	if(app.login in appHost.config.users) {
		firstrun = appHost.config.users[app.login].firstrun;
	}
	if(firstrun) {
		var x = $.msg({
			text: "For security reasons, please, change default password!",
			delay: -1,
		});
		x.addChild(
			$.element()
				.addClass("row")
				.addChild(
					$.element
						.button("Change Password")
						.addClass("col-4")
						.on("click", function(event) {
							x.remove();
							SettingsUsersModule.openConfig(app.login);
						})
				)
		);
	}
};

MainModule.init = function() {
	$.body.bindScope(renderCards, {});
};

app.modules.push(MainModule);
app.menu.push(MainModule);
})();

/* stream.js */

(function() {
"use strict";

window.StreamsModule = {};

StreamsModule.makeUrl = function(x) {
	var a = x.format + "://";
	if(x.login) {
		a += x.login;
		if(x.password) a += ":" + x.password;
		a += "@";
	}
	if(x.host) a += x.host;
	if(x.port) a += ":" + x.port;
	if(x.path) a += x.path;
	return a;
};

var renderSoftcam = function(form, appHost) {
	var softcamList = [
		{ value: "", label: "None" },
		{ value: "", label: "---", disabled: true },
	];
	var softcamSortedList = [];
	$.forEach(appHost.config.softcam, function(i) {
		softcamSortedList.push({
			value: i.id,
			label: i.name,
		});
	});
	softcamSortedList.sort(function(a, b) {
		return a.label.localeCompare(b.label);
	});
	softcamList = softcamList.concat(softcamSortedList);
	form.choice("SoftCAM", "cam", softcamList);
	form.input("BISS Key", "biss").addValidator(validateBiss);
};

StreamsModule.renderModal_input = function(hostId) {
	var modal = this,
		appHost = app.hosts[hostId],
		form = new Form(modal.scope, modal),
		format = modal.scope.get("format");
	form.checkbox("Enable", "$enable").addAttr("data-false", "false");
	form.choice("Input Type", "format", [
		{ value: "", label: "" },
		{ value: "srt", label: "SRT" },
		{ value: "dvb", label: "DVB" },
		{ value: "http", label: "HTTP/HLS" },
		{ value: "https", label: "HTTPS/HLS" },
		{ value: "udp", label: "UDP" },
		{ value: "rtp", label: "RTP" },
		{ value: "rtsp", label: "RTSP" },
		{ value: "file", label: "MPEG-TS Files" },
	])
		.setRequired()
		.on("change", function() {
			modal.scope.reset({
				$enable: modal.scope.get("$enable"),
				format: this.value,
			});
		});
	if(!!format) form.hr();
	if(format == "dvb") {
		var aList = [{ value: "", label: "" }];
		$.forEach(MainModule.adapters, function(a) {
			if(a.$host == hostId) {
				aList.push({
					value: a.$config.id,
					label: a.$config.name,
				});
			}
		});
		form.choice("Adapter", "addr", aList).setRequired();
		form.checkbox("DVB-CI CAM", "cam");
		form.number("T2-MI", "t2mi");
		form.number("PNR", "pnr", "Program Number").addValidator(validatePnr);
		form.number("DD-CI CAM", "ddci");
		renderSoftcam(form, appHost);
	} else if(format == "http" || format == "https") {
		var a = modal.scope.serialize();
		modal.scope.set("$addr", makeUrl(a).split("#")[0]);
		form.input("HTTP Address", "$addr", "http://...")
			.setRequired()
			.addValidator(validateUrl)
			.on("input", function() {
				$.forEach(parseUrl(this.value), function(v, k) {
					if(a[k] != v) {
						a[k] = v;
						modal.scope.set(k, v);
					}
				});
			});
		form.input("User-Agent", "ua", "Custom HTTP User-Agent. Default: Astra");
		if(modal.scope.get("$advanced")) {
			form.hr();
			form.number("Buffer Time", "buffer_time", "Receiving buffer in seconds. Default: 2");
			form.number("Timeout", "timeout", "Connection timeout in seconds. Default: 10");
			form.checkbox("Use SCTP instead of TCP", "sctp");
		}
		form.hr();
		form.number("PNR", "pnr", "Program Number").addValidator(validatePnr);
		form.number("DD-CI CAM", "ddci");
		renderSoftcam(form, appHost);
		form.checkbox("Advanced Options", "$advanced").on("change", function() {
			modal.scope.reset();
		});
	} else if(format == "udp" || format == "rtp") {
		var if_list = [{ value: "", label: "Default: Use system route" }];
		$.forEach(appHost.sysinfo.if_list, function(v) {
			if_list.push(v);
		});
		form.choice("Local Interface", "localaddr", if_list);
		form.input("Address", "addr", "Source Address").setRequired();
		form.number("Port", "port", "Source Port. Default: 1234").addValidator(validatePort);
		if(modal.scope.get("$advanced")) {
			form.hr();
			form.number("Renew", "renew", "Refresh multicast group membership");
			form.number("Socket Size", "socket_size", "Redefine system socket size");
		}
		form.hr();
		form.number("PNR", "pnr", "Program Number").addValidator(validatePnr);
		form.number("DD-CI CAM", "ddci");
		renderSoftcam(form, appHost);
		form.checkbox("Advanced Options", "$advanced").on("change", function() {
			modal.scope.reset();
		});
	} else if(format == "rtsp") {
		var a = modal.scope.serialize();
		modal.scope.set("$addr", makeUrl(a).split("#")[0]);
		form.input("RTSP Address", "$addr", "rtsp://...")
			.setRequired()
			.addValidator(validateUrl)
			.on("input", function() {
				$.forEach(parseUrl(this.value), function(v, k) {
					if(a[k] != v) {
						a[k] = v;
						modal.scope.set(k, v);
					}
				});
			});
		form.checkbox("Interleaved mode. Send data over TCP", "tcp");
	} else if(format == "file") {
		form.input("File", "filename", "Full path to the MPEG-TS file").setRequired();
		form.checkbox("Repeat File", "loop");
		form.number("PNR", "pnr", "Program Number").addValidator(validatePnr);
	} else if(format == "srt") {
		const is_caller = modal.scope.get("localaddr") == undefined;
		modal.scope.set("$srt_mode", is_caller ? "caller" : "listener");

		form.choice("SRT Mode", "$srt_mode", [
			{ value: "caller", label: "Caller" },
			{ value: "listener", label: "Listener" },
		]).on("change", function() {
			modal.scope.reset({
				$enable: modal.scope.get("$enable"),
				format: format,
				localaddr: (this.value == "caller") ? undefined : "",
			});
		});

		if(is_caller) {
			form.input("Address", "addr", "Source Address").setRequired();
			form.number("Port", "port", "Source Port").setRequired().addValidator(validatePort);
		} else {
			var if_list = [{ value: "", label: "Default: Any interface" }];
			$.forEach(appHost.sysinfo.if_list, function(v) {
				if_list.push(v);
			});
			form.choice("Local Interface", "localaddr", if_list);
			form.number("Port", "port", "Local Port").setRequired().addValidator(validatePort);
		}

		form.hr();
		form.number("Timeout", "timeout", "Default: 5");
		form.number("Latency", "latency", "Default: 120");
		if(is_caller) form.input("Stream ID", "streamid");
		form.input("Passphrase", "passphrase");
		form.choice("Crypto key length", "pbkeylen", [
			{ value: "", label: "Default: 16 AES-128" },
			{ value: "24", label: "24 AES-192" },
			{ value: "32", label: "32 AES-256" },
		]);
		form.checkbox("Timestamp-based packet delivery mode", "tsbpdmode");
	}
	form.hr();
	var btnOk = $.element
		.button("Ok")
		.addClass("submit")
		.on("click", function() {
			modal.submit();
		});
	var btnCancel = $.element
		.button("Cancel")
		.on("click", function() {
			modal.remove();
		});
	form.checkbox("Remove", "$remove")
		.setDanger()
		.on("change", function() {
			if(this.checked) btnOk.removeClass("submit").addClass("danger");
			else btnOk.removeClass("danger").addClass("submit");
		});
	form.submit().addChild(btnOk, btnCancel);
};

StreamsModule.renderModal_output = function(hostId) {
	var modal = this,
		appHost = app.hosts[hostId],
		form = new Form(modal.scope, modal),
		format = modal.scope.get("format");
	form.checkbox("Enable", "$enable").addAttr("data-false", "false");
	form.choice("Output Type", "format", [
		{ value: "", label: "" },
		{ value: "srt", label: "SRT" },
		{ value: "http", label: "HTTP/HLS" },
		{ value: "udp", label: "UDP" },
		{ value: "rtp", label: "RTP" },
		{ value: "resi", label: "RESI Modulator" },
		{ value: "np", label: "NetworkPush" },
		{ value: "file", label: "MPEG-TS Files" },
	])
		.setRequired()
		.on("change", function() {
			modal.scope.reset({
				$enable: modal.scope.get("$enable"),
				format: this.value,
			});
		});
	if(!!format) form.hr();
	if(format == "http") {
		form.input("Address", "host", "Interface IP address or 0 for any interface").setRequired();
		form.number("Port", "port", "HTTP Server port").setRequired().addValidator(validatePort);
		form.input("Path", "path", "Unique path for stream")
			.setRequired()
			.addValidator(function(value) {
				return value[0] == "/";
			});
	} else if(format == "udp" || format == "rtp") {
		var if_list = [{ value: "", label: "Default: Use system route" }];
		$.forEach(appHost.sysinfo.if_list, function(v) {
			if_list.push(v);
		});
		form.choice("Local Interface", "localaddr", if_list);
		form.input("Address", "addr", "Destination Address").setRequired();
		form.number("Port", "port", "Destination Port. Default: 1234").addValidator(validatePort);
	} else if(format == "resi") {
		form.number("Adapter", "adapter").setRequired();
		form.number("Device", "device").setRequired();
		form.number("Frequency", "frequency", "114..858 MHz")
			.setRequired()
			.addValidator(function(value) {
				value = Number(value);
				return !isNaN(value) && value > 113 && value < 858 && (value - 114) % 8 == 0;
			});
		form.choice("Modulation", "modulation", [
			{ value: "", label: "Default: 64-QAM" },
			{ value: "QAM16", label: "16-QAM" },
			{ value: "QAM32", label: "32-QAM" },
			{ value: "QAM128", label: "128-QAM" },
			{ value: "QAM256", label: "256-QAM" },
		]);
		form.number("Symbol Rate", "symbolrate", "1000...7100").addValidator(function(value) {
			if(value == undefined || value == "") return true;
			value = Number(value);
			return !isNaN(value) && value >= 1e3 && value <= 7100;
		});
		form.number("Attenuator", "attenuator", "0...31").addValidator(function(value) {
			if(value == undefined || value == "") return true;
			value = Number(value);
			return !isNaN(value) && value >= 0 && value <= 31;
		});
	} else if(format == "np") {
		var a = modal.scope.serialize();
		modal.scope.set("$addr", makeUrl(a).split("#")[0]);
		form.input("Address", "$addr", "np://...")
			.setRequired()
			.addValidator(validateUrl)
			.on("input", function() {
				$.forEach(parseUrl(this.value), function(v, k) {
					if(a[k] != v) {
						a[k] = v;
						modal.scope.set(k, v);
					}
				});
			});
	} else if(format == "file") {
		form.input("File", "filename", "Full path to the MPEG-TS file").setRequired();
	} else if(format == "srt") {
		const is_caller = modal.scope.get("localaddr") == undefined;
		modal.scope.set("$srt_mode", is_caller ? "caller" : "listener");

		form.choice("SRT Mode", "$srt_mode", [
			{ value: "caller", label: "Caller" },
			{ value: "listener", label: "Listener" },
		]).on("change", function() {
			modal.scope.reset({
				$enable: modal.scope.get("$enable"),
				format: format,
				localaddr: (this.value == "caller") ? undefined : "",
			});
		});

		if(is_caller) {
			form.input("Address", "addr", "Destination Address").setRequired();
			form.number("Port", "port", "Destination Port").setRequired().addValidator(validatePort);
		} else {
			var if_list = [{ value: "", label: "Default: Any interface" }];
			$.forEach(appHost.sysinfo.if_list, function(v) {
				if_list.push(v);
			});
			form.choice("Local Interface", "localaddr", if_list);
			form.number("Port", "port", "Local Port").setRequired().addValidator(validatePort);
		}

		form.hr();
		form.number("Timeout", "timeout", "Default: 5");
		form.number("Latency", "latency", "Default: 120");
		if(is_caller) form.input("Stream ID", "streamid");
		form.input("Passphrase", "passphrase");
		form.choice("Crypto key length", "pbkeylen", [
			{ value: "", label: "Default: 16 AES-128" },
			{ value: "24", label: "24 AES-192" },
			{ value: "32", label: "32 AES-256" },
		]);
		form.checkbox("Timestamp-based packet delivery mode", "tsbpdmode");
	}
	form.hr();
	var btnOk = $.element
		.button("Ok")
		.addClass("submit")
		.on("click", function() {
			modal.submit();
		});
	var btnCancel = $.element
		.button("Cancel")
		.on("click", function() {
			modal.remove();
		});
	form.checkbox("Remove", "$remove")
		.setDanger()
		.on("change", function() {
			if(this.checked) btnOk.removeClass("submit").addClass("danger");
			else btnOk.removeClass("danger").addClass("submit");
		});
	form.submit().addChild(btnOk, btnCancel);
};

StreamsModule.startAnalyze = function(hostId, streamId) {
	var appHost = app.hosts[hostId];
	StreamsModule.modalAnalyze = $.modal();
	var form = new Form({}, StreamsModule.modalAnalyze);
	var content = form.group();
	form.hr();
	var btnOk = $.element
		.button("Close")
		.addClass("submit")
		.on("click", function() {
			StreamsModule.modalAnalyze.remove();
		});
	var btnCopy = $.element
		.button("Copy")
		.on("click", function() {
			analyzeUi.copy();
			$.msg({
				title: "Analyzer data copied to the clipboard",
			});
		});
	form.submit().addChild(btnOk, btnCopy);
	analyzeUi.render(content);
	var scanId;
	var onScan = function(event) {
		analyzeUi.process(event.data.data);
	};
	var start = function() {
		appHost.request({
			cmd: "scan-init",
			scan: "stream://" + streamId,
			ws: appHost.wsid,
		}, function(response) {
			if(response.data["scan-init"] === "ok") scanId = response.data["id"];
			else if(response.data["error"]) {
				$.err({
					title: response.data["error"],
				});
			}
		}, function() {
			$.err({
				title: "scan-init failed",
			});
		});
	};
	var stop = function() {
		if(!scanId) return;
		appHost.request({
			cmd: "scan-kill",
			id: scanId,
		}, function(response) {
		}, function() {
			$.err({
				title: "scan-kill failed",
			});
		});
		scanId = undefined;
	};
	app.on("scan", onScan);
	start();
	var onDestroy = function() {
		if(StreamsModule.modalAnalyze) StreamsModule.modalAnalyze.remove();
	};
	var onModalRemove = function() {
		stop();
		app.off("scan", onScan);
		$.body.off("destroy", onDestroy);
		analyzeUi.destroy();
		delete StreamsModule.modalAnalyze;
	};
	StreamsModule.modalAnalyze.on("remove", function() {
		onModalRemove();
	});
	$.body.on("destroy", onDestroy);
};

var ioList = function(self, form, ioType, hostId) {
	form.hr();
	var lE = self.scope.get(ioType),
		lD = self.scope.get("_" + ioType);
	if(!lE) {
		lE = [""];
		self.scope.set(ioType, lE);
	}
	if(!lD) {
		lD = [];
		self.scope.set("_" + ioType, lD);
	}

	var renderIoList = function(ioEnable) {
		var l = ioEnable ? lE : lD;
		$.forEach(l, function(v, i) {
			const ioID = (ioEnable ? "" : "_") + ioType + "." + i;

			let opts = null;
			if(v) {
				const u = new URL(v);
				opts = new URLSearchParams(u.hash.slice(1));
			} else {
				opts = new URLSearchParams();
			}

			var name = "";
			if(ioEnable) name += "#" + (i + 1);
			if(opts.has("name")) name += " " + opts.get("name");

			var x = form.input(name, ioID);

			// get label
			x.nextElementSibling
				.addClass("editable")
				.on("click", function() {
					if(x.hasClass("error") || !x.value) return;

					let result = prompt(`Enter ${ ioType } name`, opts.get("name") || "");
					if(result === null) return;
					result = result.trim();

					// update title
					name = ""
					if(ioEnable) name += "#" + (i + 1);
					if(result != "") name += " " + result;
					x.nextElementSibling.setText(name);

					const kv = "name=" + encodeURIComponent(result);
					let xv = x.value;

					const u = new URL(xv);
					const o = new URLSearchParams(u.hash.slice(1));

					if(!o.has("name")) {
						if(!result) return;

						if(!u.hash) {
							xv += "#" + kv
						} else {
							xv += "&" + kv
						}
					} else {
						const h = u.hash.replace(/\bname=([^&]*)/, (!result) ? "" : kv)
						xv = xv.split("#")[0]
						if(h != "#") xv += h
					}

					xv = xv.trim();
					x.value = xv;
					self.scope.set(x.dataset.bind, xv);
				});

			x.addValidator(validateUrl);
			x.on("blur", function() {
				self.scope.set(x.dataset.bind, this.value.trim());
			});
			x.on("keydown", function(event) {
				if(event.keyCode == 13) {
					event.preventDefault();
					x.blur();
					var n;
					if(event.shiftKey) {
						if(i == 0) {
							n = 0;
							l.splice(0, 0, "");
							self.scope.reset();
						} else {
							n = i - 1;
						}
					} else {
						n = i + 1;
						if(n == l.length) {
							l.push("");
							self.scope.reset();
						}
					}
					document.querySelector('[name="' + (ioEnable ? "" : "_") + ioType + "." + n + '"]').focus();
				}
			});
			if(ioType == "input") {
				var s = $.element("select")
					.addClass("button icon icon-move")
					.on("change", function() {
						if(this.value == "-2") {
							l.splice(i, 1);
							if(!lE.length) lE.push("");
						} else if(this.value == "-1") {
							lD.push(lE.splice(i, 1)[0]);
							if(!lE.length) lE.push("");
						} else {
							var _i = i;
							if(!ioEnable) {
								_i = lE.length;
								lE.push(lD.splice(i, 1)[0]);
							}
							lE.move(_i, Number(this.value));
						}
						self.scope.reset();
					});
				for(var j = 0; j < lE.length; ++j) {
					s.addChild(
						$.element("option")
							.setValue(j.toString())
							.setText(j + 1)
					);
				}
				if(!ioEnable) {
					s.addChild(
						$.element("option")
							.setValue(lE.length.toString())
							.setText(lE.length + 1)
					);
				}
				s.addChild(
					$.element("option")
						.setDisabled(true)
						.setText("---"),
					$.element("option")
						.setValue("-1")
						.setText("Disable"),
					$.element("option")
						.setValue("-2")
						.setText("Remove")
				);
				s.value = ioEnable ? i.toString() : "-1";
				x.addButton(s);
			}
			x.addButton(
				$.element
					.button()
					.addClass("icon icon-settings")
					.on("click", function() {
						var modalData = parseUrl(x.value) || {};
						modalData.$enable = ioEnable;
						$.modal()
							.bindScope(StreamsModule["renderModal_" + ioType], modalData, hostId)
							.on("submit", function() {
								l.splice(i, 1);
								if(!this.scope.get("$remove")) {
									var lM = this.scope.get("$enable") ? lE : lD;
									lM.push(makeUrl(this.scope.serialize()));
									if(lM == l) l.move(l.length - 1, i);
								}
								if(!lE.length) lE.push("");
								var x = window.scrollTop;
								self.scope.reset();
								window.scrollTop = x;
							});
					})
			);
		});
	};

	form.header(ioType + " list", "new " + ioType, function() {
		lE.push("");
		self.scope.reset();
		document.querySelector('[name="' + ioType + "." + (lE.length - 1) + '"]').focus();
	});

	renderIoList(true);

	if(!lD.length) return;
	form.header("Disabled " + ioType + "'s");
	renderIoList(false);
};

var tabGeneral = function(self, form, streamId, hostId) {
	form.checkbox("Enable", "enable").addAttr("data-false", "false");
	form.input("Name", "name").setRequired();
	var x = form.input("ID", "id")
		.addValidator(validateId)
		.addValidator((v) => (v == streamId) || !MainModule.streams.hasOwnProperty(hostId + "/" + v));

	form.checkbox("Create Multi Program Stream", "type")
		.addAttr("data-false", "spts")
		.addAttr("data-true", "mpts")
		.on("change", function() {
			self.scope.reset({
				enable: self.scope.get("enable"),
				id: self.scope.get("id"),
				type: this.checked ? "mpts" : "spts",
				name: self.scope.get("name"),
				groups: self.scope.get("groups"),
				input: self.scope.get("input"),
				output: self.scope.get("output"),
			});
		});
};

var tabGroups = function(self, form) {
	var masterHost = app.hosts[location.host];
	if(!masterHost.config.categories) {
		form.group()
			.addClass("text-center")
			.setHtml('Create new group in <a href="#/settings-groups">Settings &gt; Groups</a>');
	} else {
		$.forEach(masterHost.config.categories, function(c) {
			var gl = [{ value: "", test: "" }];
			$.forEach(c.groups, function(g) {
				gl.push({ value: g.name, label: g.name });
			});
			form.choice(c.name, "groups." + c.name.replace(/\./g, "\\."), gl);
		});
	}
};

var tabSpts = function(self, form, streamId, hostId) {
	tabGeneral(self, form, streamId, hostId);

	form.text("Description", "info");
	ioList(self, form, "input", hostId);
	ioList(self, form, "output", hostId);
};

var tabSptsSdt = function(self, form, streamId, hostId) {
	form.choice("Service Type", "service_type", [
		{ value: "", label: "Default: original service type" },
		{ value: "1", label: "0x01 Digital television service" },
		{ value: "2", label: "0x02 Digital radio sound service" },
		{ value: "3", label: "0x03 Teletext service" },
		{ value: "10", label: "0x0A Advanced codec digital radio sound service" },
		{ value: "12", label: "0x0C Data broadcast service" },
		{ value: "16", label: "0x10 DVB MHP service" },
		{ value: "17", label: "0x11 MPEG-2 HD digital television service" },
		{ value: "22", label: "0x16 Advanced codec SD digital television service" },
		{ value: "25", label: "0x19 Advanced codec HD digital television service" },
	]);
	form.input("Service Provider", "service_provider");
	form.input("Service Name", "service_name");
	form.choice("Codepage", "textcode", codepages);
	form.hr();
	form.input("HbbTV URL", "hbbtv_url");
	form.hr();
	var casChannelList = self.scope.get("cas_list");
	form.header("Conditional Access", "New CAS", function() {
		if(!casChannelList) {
			casChannelList = [];
			self.scope.set("cas_list", casChannelList);
		}
		casChannelList.push({});
		self.scope.reset();
	});
	var casGlobalList = [
		{ value: "", label: "None" },
		{ value: "", label: "---", disabled: true },
	];
	var casSortedList = [];
	$.forEach(app.hosts[hostId].config.cas, function(i) {
		casSortedList.push({
			value: i.id,
			label: i.name + " [" + i.super_cas_id + "]",
		});
	});
	casSortedList.sort(function(a, b) {
		return a.label.localeCompare(b.label);
	});
	casGlobalList = casGlobalList.concat(casSortedList);
	$.forEach(casChannelList, function(cas, x) {
		if(x != 0) form.hr();
		form.choice("CAS #" + (x + 1), "cas_list." + x + ".cas_id", casGlobalList)
			.setRequired()
			.on("change", function() {
				self.scope.reset();
			});
		form.number("ECM PID", "cas_list." + x + ".ecm_pid")
			.setRequired()
			.addValidator(validatePid);
		form.input("ECM Private Data (hex)", "cas_list." + x + ".ecm_data")
			.addValidator(validateHex)
			.addAttr("maxlength", "512");
		form.input("Access Criteria (hex)", "cas_list." + x + ".ac")
			.addValidator(validateHex)
			.addAttr("maxlength", "512");
		form.group()
			.addClass("text-right")
			.addChild(
				$.element
					.button("Remove CAS")
					.addClass("link danger")
					.on("click", function() {
						casChannelList.splice(x, 1);
						if(!casChannelList.length) self.scope.set("cas_list");
						self.scope.reset();
					})
			);
	});
};

var tabSptsRemap = function(self, form) {
	form.input("Map PID's", "map", "Example: pmt=100, video=101, audio=102, 1003=103");
	form.input("Filter PID's", "filter~", "Keep only defined pids. Example: 101, 102, 103");
	form.number("Change PNR", "set_pnr").addValidator(validatePnr);
	form.number("Change TSID", "set_tsid");
};

var tabSptsBackup = function(self, form) {
	form.choice("Backup Type", "backup_type", [
		{ value: "", label: "Default: Active Backup" },
		{ value: "stop", label: "Active Backup and Stop streaming if all inputs are inactive" },
		{ value: "passive", label: "Passive Backup" },
		{ value: "disable", label: "Disable" },
	]).on("change", function() {
		self.scope.reset();
	});
	var backup_type = self.scope.get("backup_type");
	if(backup_type != "disable") {
		form.number("Initial Delay", "backup_initial_delay", "Delay before start next input on channel launch. Default: 5 for UDP,SRT; 10 for HTTP,RTSP; 120 for DVB");
		form.number("Start Delay", "backup_start_delay", "Delay before start next input. Default: 5");
		if(backup_type != "passive") {
			form.number("Return Delay", "backup_return_delay", "Delay before return to previous input. Default: 30");
		}
	}
};

var tabSptsEpg = function(self, form) {
	form.input("XMLTV Channel ID", "xmltv_id");
	form.header("EPG Export");
	form.choice("Format", "epg_export_format", [
		{ value: "", label: "Default: XMLTV" },
		{ value: "json", label: "JSON" },
	]);
	form.input("Destination", "epg_export", "Destination address: file:// or http://");
	var x = form.choice("Codepage", "epg_export_codepage", codepages);
	x.firstChild.setText("Default: Auto");
};

var tabSptsAdvanced = function(self, form) {
	form.checkbox("Enable monitoring", "no_event")
		.addAttr("data-true", "undefined")
		.addAttr("data-false", "true");

	form.number("Channel Number", "lcn", "Logical number to arrange playlist");

	form.checkbox("Start stream on demand", "http_keep_active")
	.addAttr("data-true", "undefined")
	.addAttr("data-false", "-1")
	.on("change", function() {
		self.scope.reset();
	});
	if(self.scope.get("http_keep_active") != -1) {
		form.number("Keep Active", "http_keep_active", "Delay before stop stream if no active connections. Default: 0 (turn off immediately)");
	}

	form.input("HLS Header", "hls_header", "Parameters for HLS stream information");
}

var tabMpts = function(self, form, streamId, hostId) {
	tabGeneral(self, form, streamId, hostId);
	form.input("Country", "country", "Country Code ISO 3166-1 alpha-3")
		.setRequired()
		.addValidator(function(value) {
			return !!value && value.length == 3;
		});
	form.input("UTC Offset", "offset", "Offset time from UTC in the range between -720 minutes and +780 minutes");
	form.number("Network ID", "network_id", "Default: 1");
	form.input("Network Name", "network_name");
	form.input("Provider Name", "provider");
	form.choice("Codepage", "textcode", codepages);
	form.number("TSID", "tsid", "Transport Stream ID. Default: 1").addAttr("maxlength", "5");
	form.number("ONID", "onid", "Original Network ID. Default: 1");
	ioList(self, form, "input", hostId);
	ioList(self, form, "output", hostId);
};

var tabMptsSdt = function(self, form) {
	var sl = self.scope.get("sdt");
	$.forEach(sl, function(v, k) {
		var s = $.element("select")
			.addClass("button icon icon-move")
			.setStyle("float", "right")
			.on("change", function() {
				if(this.value == "-1") {
					sl.splice(k, 1);
				} else {
					sl.move(k, Number(this.value));
				}
				self.scope.reset();
			});
		for(var i = 0; i < sl.length; i++) {
			s.addChild(
				$.element("option")
					.setValue(i.toString())
					.setText(i + 1)
			);
		}
		s.addChild(
			$.element("option")
				.setDisabled(true)
				.setText("---"),
			$.element("option")
				.setValue("-1")
				.setText("Remove")
		);
		s.value = k;
		form.header("Service #" + (k + 1)).addChild(s);
		form.choice("Service Type", "sdt." + k + ".type", [
			{ value: "1", label: "0x01 Digital television service" },
			{ value: "2", label: "0x02 Digital radio sound service" },
			{ value: "3", label: "0x03 Teletext service" },
			{ value: "10", label: "0x0A Advanced codec digital radio sound service" },
			{ value: "12", label: "0x0C Data broadcast service" },
			{ value: "16", label: "0x10 DVB MHP service" },
			{ value: "17", label: "0x11 MPEG-2 HD digital television service" },
			{ value: "22", label: "0x16 Advanced codec SD digital television service" },
			{ value: "25", label: "0x19 Advanced codec HD digital television service" },
		]);
		form.input("Service Name", "sdt." + k + ".name").setRequired();
		form.number("PNR", "sdt." + k + ".pnr", "Program Number")
			.setRequired()
			.addValidator(validatePnr);
		form.checkbox("Scrambled channel", "sdt." + k + ".ca").on("change", function() {
			self.scope.reset();
		});
		form.number("LCN", "sdt." + k + ".lcn", "Logical Channel Number").addValidator(function(value) {
			if(value == undefined || value == "") return true;
			value = Number(value);
			return !isNaN(value) && value >= 0 && value < 1e3;
		});
		form.hr();
	});
	form.header("New Service").addChild(
		$.element
			.button()
			.addClass("icon  icon-add")
			.setStyle("float", "right")
			.on("click", function(event) {
				event.preventDefault();
				if(sl == undefined) {
					sl = [];
					self.scope.set("sdt", sl);
				}
				sl.push({ type: "1" });
				self.scope.reset();
				window.scrollTo(0, $.base.scrollHeight);
				document.querySelector('[name="sdt.' + (sl.length - 1) + '.name"]').focus();
			})
	);
};

var tabMptsNit = function(self, form, streamId, hostId) {
	form.choice("LCN Version", "nit_actual.lcn_version", [
		{ value: "", label: "Default: EACEM" },
		{ value: "nordig-v1", label: "Nordig v1" },
	]);
	form.hr();
	form.choice("Delivery Type", "nit_actual.type", [
		{ value: "", label: "Default: not defined" },
		{ value: "S", label: "DVB-S" },
		{ value: "C", label: "DVB-C" },
		{ value: "T", label: "DVB-T" },
	]).on("change", function() {
		self.scope.set("nit_actual", {
			type: this.value,
		});
		self.scope.set("nit_other", undefined);
		self.scope.reset();
	});
	var sType = self.scope.get("nit_actual.type");
	if(!sType) {
	} else if(sType == "S") {
		form.number("Frequency", "nit_actual.frequency", "950..13250 MHz")
			.setRequired()
			.addValidator(function(value) {
				value = Number(value);
				return !isNaN(value) && value >= 950 && value < 13250;
			});
		form.choice("Polarization", "nit_actual.polarization", dvbPolarization).setRequired();
		form.number("Symbolrate", "nit_actual.symbolrate", "1000..50000 Kbaud")
			.setRequired()
			.addValidator(function(value) {
				value = Number(value);
				return !isNaN(value) && value > 1e3 && value < 5e4;
			});
		form.input("Orbital Position", "nit_actual.position", "Orbital Position (Example: 0.8W, 36.0E)")
			.setRequired()
			.addValidator(function(value) {
				return true;
			});
		form.choice("FEC", "nit_actual.fec", dvbFec);
		form.choice("Modulation", "nit_actual.modulation", dvbsModulation);
	} else if(sType == "C") {
		form.number("Frequency", "nit_actual.frequency", "80..1000 MHz")
			.setRequired()
			.addValidator(function(value) {
				value = Number(value);
				return !isNaN(value) && value >= 80 && value < 1e3;
			});
		form.number("Symbolrate", "nit_actual.symbolrate", "1000..10000 Kbaud")
			.setRequired()
			.addValidator(function(value) {
				value = Number(value);
				return !isNaN(value) && value > 1e3 && value < 1e4;
			});
		form.choice("FEC", "nit_actual.fec", dvbFec);
		form.choice("Modulation", "nit_actual.modulation", dvbcModulation);
	} else if(sType == "T") {
		form.number("Frequency", "nit_actual.frequency", "80..1000 MHz")
			.setRequired()
			.addValidator(function(value) {
				value = Number(value);
				return !isNaN(value) && value >= 80 && value < 1e3;
			});
		form.choice("Bandwidth", "nit_actual.bandwidth", [
			{ value: "", label: "Default: 8MHz" },
			{ value: "6", label: "6MHz" },
			{ value: "7", label: "7MHz" },
		]);
		form.checkbox("High Priority", "nit_actual.priority").addAttr("data-false", "undefined").addAttr("data-true", "1");
		form.choice("Modulation", "nit_actual.modulation", dvbtModulation);
		form.choice("Guard", "nit_actual.guardinterval", [
			{ value: "", label: "Default: Auto" },
			{ value: "1/32" },
			{ value: "1/16" },
			{ value: "1/8" },
			{ value: "1/4" },
		]);
		form.choice("Transmit", "nit_actual.transmitmode", [
			{ value: "", label: "Default: Auto" },
			{ value: "2K" },
			{ value: "4K" },
			{ value: "8K" },
		]);
		form.choice("Hierarchy", "nit_actual.hierarchy", [
			{ value: "", label: "Default: Non-hierarchical, native" },
			{ value: "1", label: "1, native" },
			{ value: "2", label: "2, native" },
			{ value: "3", label: "4, native" },
			{ value: "4", label: "Default: Non-hierarchical, in-depth" },
			{ value: "5", label: "1, in-depth" },
			{ value: "6", label: "2, in-depth" },
			{ value: "7", label: "4, in-depth" },
		]);
	}
	form.header("Network Search");
	var nitOther = self.scope.get("nit_other");
	if(!nitOther) {
		nitOther = [];
		self.scope.set("nit_other", nitOther);
	}
	var mptsList = [];
	$.forEach(app.hosts[hostId].config.make_stream, function(c) {
		if(c.id && c.id != streamId && c.type == "mpts") {
			mptsList.push({
				id: c.id,
				name: c.name,
				tsid: c.tsid,
			});
		}
	});
	$.forEach(mptsList, function(c) {
		var x = form.checkbox(c.name, "").on("change", function() {
			if(this.checked) {
				nitOther.push(c.id);
			} else {
				var i = nitOther.indexOf(c.id);
				if(i != -1) nitOther.splice(i, 1);
			}
		});
		x.checked = nitOther.indexOf(c.id) != -1;
	});
};

var tabMptsAdvanced = function(self, form) {
	form.checkbox("Disable PID's auto-remap", "no_remap");
	form.number("SI Packets Interval", "si_interval", "Interval in milliseconds to send stream information. Default: 500");
	form.hr();
	form.checkbox("Pass NIT", "pass_nit");
	form.checkbox("Pass SDT", "pass_sdt");
	form.checkbox("Pass EIT", "pass_eit");
	form.checkbox("Remux EIT", "remux_eit");
	form.checkbox("Pass TDT", "pass_tdt");
	form.hr();
	form.number("PAT version", "pat_version");
	form.number("NIT version", "nit_version");
	form.number("CAT version", "cat_version");
	form.number("SDT version", "sdt_version");
};

StreamsModule.tabs = {
	spts: [
		{ label: "General", id: "spts", render: tabSpts },
		{ label: "Groups", id: "groups", render: tabGroups },
		{ label: "Service", id: "sptssdt", render: tabSptsSdt },
		{ label: "Remap", id: "remap", render: tabSptsRemap },
		{ label: "Backup", id: "backup", render: tabSptsBackup },
		{ label: "EPG", id: "epg", render: tabSptsEpg },
		{ label: "Advanced", id: "advanced", render: tabSptsAdvanced },
	],
	mpts: [
		{ label: "General", id: "mpts", render: tabMpts },
		{ label: "Groups", id: "groups", render: tabGroups },
		{ label: "SDT", id: "mptssdt", render: tabMptsSdt },
		{ label: "NIT", id: "nit", render: tabMptsNit },
		{ label: "Advanced", id: "advanced", render: tabMptsAdvanced },
	],
};

function render(hostId, streamId) {
	var x,
		self = this,
		appHost = app.hosts[hostId],
		type = self.scope.get("type"),
		tabId = self.scope.get("$tab") || type,
		form = new Form(self.scope, self),
		tabRender;

	x = [];
	$.forEach(StreamsModule.tabs[type], function(v) {
		x.push(v);
		if(tabId == v.id) tabRender = v.render;
	});
	form.tab("$tab", x);
	tabRender(self, form, streamId, hostId);
	var serialize = function() {
		if(self.scope.get("$remove")) {
			return { remove: true };
		}
		var data = self.scope.serialize();
		if(!data.id) data.id = appHost.makeUid("make_stream");
		var ioClean = function(obj) {
			var a = data[obj];
			if(a == undefined) return;
			for(var i = 0; i < a.length; ) {
				if(!a[i]) a.splice(i, 1);
				else ++i;
			}
			if(!a.length) delete data[obj];
		};
		ioClean("input");
		ioClean("_input");
		ioClean("output");
		ioClean("_output");
		if(!data.input) data.enable = false;
		if(data.nit_actual) {
			if(!data.nit_actual.type) {
				delete data.nit_actual;
				delete data.nit_other;
			} else {
				$.forEach(data.nit_actual, function(v, k) {
					if(!v) delete data.nit_actual[k];
				});
				if(data.nit_other) {
					for(var i = 0; i < data.nit_other.length; ) {
						if(data.nit_other[i]) ++i;
						else data.nit_other.splice(i, 1);
					}
					if(!data.nit_other.length) delete data.nit_other;
				}
			}
		}
		$.forEach(data.groups, function(v, k) {
			if(!v) delete data.groups[k];
		});
		if($.isObjectEmpty(data.groups)) delete data.groups;
		return data;
	};
	form.hr();
	var btnApply = $.element
		.button("Apply")
		.addClass(self.scope.get("$remove") ? "danger" : "submit")
		.on("click", function() {
			if(!self.scope.get("$remove") && !self.scope.validate()) {
				$.err({
					title: "Form has errors",
				});
				return;
			}
		var data = serialize();
		appHost.request({
			cmd: "set-stream",
			gid: appHost.config.gid,
			id: streamId,
			stream: data,
		}, function() {
			self.remove();
		}, function() {
			$.err({
				title: "Failed to save stream",
			});
		});
	});
	var btnClone = $.element.button("Clone").on("click", function() {
		var data = serialize();
		data.name = (data.name || "") + " (clone)";
		if(data.id != undefined) delete data.id;
		StreamsModule.streamClone = data;
		self.remove();
		app.selectHost(StreamsModule.modal, "-");
	});
	var btnAnalyze = $.element.button("Analyze").on("click", function() {
		StreamsModule.startAnalyze(hostId, streamId);
	});
	if(streamId != "-") {
		if(tabId == type) {
			form.checkbox("Remove", "$remove")
				.setDanger()
				.on("change", function() {
					if(this.checked) btnApply.removeClass("submit").addClass("danger");
					else btnApply.removeClass("danger").addClass("submit");
				});
		}
	} else {
		btnClone.setDisabled(true);
		btnAnalyze.setDisabled(true);
	}

	var btnCancel = $.element.button("Cancel")
		.on("click", function() {
			self.remove();
		});

	form.submit().addChild(
		btnApply,
		btnClone,
		btnAnalyze,
		btnCancel
	);
};

StreamsModule.modal = function(host, sid) {
	var scope;
	if(sid == "-") {
		if(StreamsModule.streamClone) {
			scope = StreamsModule.streamClone;
			delete StreamsModule.streamClone;
		} else {
			scope = {
				enable: true,
				type: "spts",
			};
		}
	} else {
		var s = MainModule.streams[host + "/" + sid];
		if(!s) {
			$.err({
				text: "Stream " + sid + " on " + host + " not found",
			});
			return;
		}
		scope = $.clone(s.$config);
	}
	$.modal().bindScope(render, scope, host, sid);
};

app.modules.push(StreamsModule);
})();

/* adapter.js */

(function() {
"use strict";

window.AdaptersModule = {};

AdaptersModule.renderScan = function(host) {
	var modal = this,
		appHost = app.hosts[host],
		form = new Form(modal.scope, modal);
	var i = function(t) {
		return $.element("span").addAttr("title", t);
	};
	if(modal.scope.get("satip") || modal.scope.get("virtual")) {
		var sI = $.element("div").addClass("satip-status").addChild(i("CONNECT"), i("BITRATE"));
		var xl = sI.childNodes;
		sI.setStatus = function(s) {
			xl[0].className = s.connect ? "ok" : "er";
			xl[1].setText(s.bitrate + " Kbit/s");
		};
		form.submit().addChild(sI);
		modal.setStatus = function(s) {
			sI.setStatus(s);
			modal.status = s;
		};
		modal.setStatus(modal.status || {
			connect: false,
			bitrate: 0,
		});
	} else {
		var sI = $.element("div").addClass("info-status").addChild(i("SIGNAL"), i("CARRIER"), i("FEC"), i("SYNC"), i("LOCK"), i("BER"), i("UNC"), i("S"), i("C/N"), i("BITRATE"));
		var xl = sI.childNodes;
		sI.setStatus = function(s) {
			xl[0].className = s.status & 1 ? "ok" : "er";
			xl[1].className = s.status & 2 ? "ok" : "er";
			xl[2].className = s.status & 4 ? "ok" : "er";
			xl[3].className = s.status & 8 ? "ok" : "er";
			xl[4].className = s.status & 16 ? "ok" : "er";
			xl[5].setText("BER:" + s.ber_value);
			xl[6].setText("UNC:" + s.unc_value);
			xl[7].setText("S:" + Number(s.signal_db / 100).format(2) + "dBm");
			xl[8].setText("C/N:" + Number(s.snr_db / 100).format(2) + "dB");
			xl[9].setText(s.bitrate + " Kbit/s");
		};
		var sS = MainModule.dvbLevel("S");
		var sQ = MainModule.dvbLevel("Q");
		form.submit().addChild(sI, sS, sQ);
		modal.setStatus = function(s) {
			sS.setLevel(s.signal);
			sQ.setLevel(s.snr);
			sI.setStatus(s);
			modal.status = s;
		};
		modal.setStatus(modal.status || {
			l: false,
			signal: 0,
			signal_db: 0,
			snr: 0,
			snr_db: 0,
			ber_value: 0,
			unc_value: 0,
			bitrate: 0,
		});
	}
	form.hr();
	var renderNit = function(v) {
		form.input("Provider").addAttr("readonly").setValue(v.name);
		var s = v.system || {};
		switch(s.type_id) {
			case 67:
				form.input("Position").addAttr("readonly").setValue(s.orbital_position);
				form.input("Frequency").addAttr("readonly").setValue(s.frequency);
				form.input("Polarization").addAttr("readonly").setValue(s.polarization);
				form.input("Symbolrate").addAttr("readonly").setValue(s.symbolrate);
				form.input("Modulation").addAttr("readonly").setValue(s.modulation);
				form.input("FEC").addAttr("readonly").setValue(s.fec);
				break;
			case 68:
				form.input("Frequency").addAttr("readonly").setValue(s.frequency);
				form.input("Symbolrate").addAttr("readonly").setValue(s.symbolrate);
				form.input("Modulation").addAttr("readonly").setValue(s.modulation);
				form.input("FEC").addAttr("readonly").setValue(s.fec);
				break;
			case 90:
				form.input("Frequency").addAttr("readonly").setValue(s.frequency);
				form.input("Bandwidth").addAttr("readonly").setValue(s.bandwidth);
				form.input("Guard Interval").addAttr("readonly").setValue(s.guard_interval);
				form.input("Transmit Mode").addAttr("readonly").setValue(s.transmitmode);
				form.input("Hierarchy").addAttr("readonly").setValue(s.hierarchy);
				form.input("Modulation").addAttr("readonly").setValue(s.modulation);
				break;
		}
		form.hr();
	};
	var renderItem = function(v, i) {
		if(v.pnr == 0) {
			renderNit(v);
		} else {
			var text = "PNR:" + v.pnr + "&nbsp;<strong>" + v.name + "</strong>";
			if(v.cas && v.cas.length) text += "<br/>CAS:" + v.cas.join(",&nbsp;");
			var s = !!v.streams && v.streams.length;
			if(s) text += "<br/>" + v.streams.join("<br/>");
			form.checkbox(text, "streams." + i + ".select");
		}
	};
	var streams = modal.scope.get("streams");
	if(!streams || !streams.length) {
		form.loading();
	} else {
		$.forEach(streams, renderItem);
		form.hr();
		form.checkbox("Set DVB-CI CAM for selected channels", "cam");
		var softcamList = [
			{ value: "", label: "None" },
			{ value: "", label: "---", disabled: true },
		];
		var softcamSortedList = [];
		$.forEach(appHost.config.softcam, function(i) {
			softcamSortedList.push({
				value: i.id,
				label: i.name,
			});
		});
		softcamSortedList.sort(function(a, b) {
			return a.label.localeCompare(b.label);
		});
		softcamList = softcamList.concat(softcamSortedList);
		form.choice("Set SoftCAM for selected channels", "cam", softcamList);
	}
	form.hr();
	var btnApply = $.element
		.button("Apply")
		.addClass("submit")
		.on("click", function() {
			modal.submit();
		});
	var btnCancel = $.element
		.button("Cancel")
		.on("click", function() {
			modal.remove();
		});
	modal.addChild(
		$.element("div")
			.addClass("text-center")
			.addChild(btnApply, btnCancel)
	);
};

AdaptersModule.startScan = function(host, fn) {
	var self = this,
		scan,
		modal,
		config = self.scope.serialize();
	config.format = "dvb";
	if(config.id == undefined) config.id = "-";
	var onScan = function(scanData) {
		modal.scope.set("streams", $.clone(scanData));
		modal.scope.reset();
	};
	var onEvent = function(event) {
		var data = event.data;
		if(event.host != host || data.dvb_id != config.id) return;
		var status;
		if(data.satip) {
			status = {
				bitrate: data.bitrate,
				connect: data.status == 8,
			};
		} else {
			if(data.signal > 100) data.signal = Math.floor((data.signal * 99) / 65535);
			if(data.snr > 100) data.snr = Math.floor((data.snr * 99) / 65535);
			if(data.signal_db == undefined) data.signal_db = 0;
			if(data.snr_db == undefined) data.snr_db = 0;
			status = {
				bitrate: data.bitrate,
				status: data.status,
				signal: data.signal,
				signal_db: data.signal_db,
				snr: data.snr,
				snr_db: data.snr_db,
				ber_value: data.ber > 99 ? "99+" : data.ber,
				unc_value: data.unc > 99 ? "99+" : data.unc,
			};
		}
		modal.setStatus(status);
	};
	var onModalRemove = function() {
		app.off("adapter_event", onEvent);
		scan.destroy();
		modal.scope.destroy();
	};

	modal = $.modal()
		.addClass("dvb-scan")
		.bindScope(AdaptersModule.renderScan, {
			satip: config.satip,
			virtual: config.virtual,
		}, host)
		.on("remove", function() {
			onModalRemove();
		})
		.on("submit", function() {
			var streams = [],
				cam = modal.scope.get("cam");
			$.forEach(modal.scope.get("streams"), function(s) {
				if(s.select) {
					streams.push({
						name: s.name,
						pnr: s.pnr,
					});
				}
			});
			onModalRemove();
			if(streams.length) fn(streams, cam);
		});

	app.on("adapter_event", onEvent);
	scan = new Scan(host, config, onScan);
};

AdaptersModule.renderPlsCals = function() {
	var modal = this,
		form = new Form(modal.scope, modal);
	form.choice("PLS Mode", "mode", [
		{ label: "Root", value: 0 },
		{ label: "Gold", value: 1 },
	]).setRequired();
	form.number("PLS Code (0 - 262143)", "code")
		.setRequired()
		.addValidator(function(value) {
			value = Number(value);
			return !isNaN(value) && value >= 0 && value <= 262143;
		});
	form.number("Stream (0 - 255)", "id")
		.setRequired()
		.addValidator(function(value) {
			value = Number(value);
			return !isNaN(value) && value >= 0 && value <= 255;
		});
	form.hr();
	var btnOk = $.element
		.button("Ok")
		.addClass("submit")
		.on("click", function() {
			if(modal.scope.validate()) modal.submit();
		});
	var btnCancel = $.element
		.button("Cancel")
		.on("click", function() {
			modal.remove();
		});
	form.submit().addChild(btnOk, btnCancel);
};

function render(hostId, adapterId) {
	var x,
		self = this,
		appHost = app.hosts[hostId],
		tabId = self.scope.get("$tab") || "",
		dvbList = MainModule.dvbDevList[hostId],
		form = new Form(self.scope, self),
		adapterType = self.scope.get("type"),
		adapterTypeMap = {
			S: "S",
			S2: "S",
			T: "T",
			T2: "T",
			C: "C",
			"C/A": "C",
			"C/B": "C",
			"C/C": "C",
			ATSC: "ATSC",
			ISDBT: "ISDBT",
		},
		adapterTypeBase = adapterTypeMap[adapterType],
		isSatIp = self.scope.get("satip") != undefined,
		virtual = self.scope.get("virtual");

	switch(adapterTypeBase) {
		case "S":
			form.tab("$tab", [
				{ label: "General", id: "" },
				{ label: "LNB", id: "lnb" },
				{ label: "Advanced", id: "advanced" },
			]);
			break;
		case "T":
		case "C":
		case "ATSC":
		case "ISDBT":
			form.tab("$tab", [
				{ label: "General", id: "" },
				{ label: "Advanced", id: "advanced" },
			]);
			break;
		default:
			form.tab("$tab", [
				{ label: "General", id: "" },
			]);
			break;
	}
	if(tabId == "") {
		form.checkbox("Enable", "enable").addAttr("data-false", "false");
		form.input("Name", "name", "Adapter Name").setRequired();
		x = form.input("ID", "id")
			.addValidator(validateId)
			.addValidator((v) => (v == adapterId) || !MainModule.adapters.hasOwnProperty(hostId + "/" + v));

		form.choice("Virtual", "virtual", [
			{ value: "" },
			{ label: "CI", value: "ci" },
			{ label: "MPTS", value: "mpts" },
			{ label: "SAT>IP", value: "satip" },
		]).on("change", function() {
			self.scope.reset({
				virtual: self.scope.get("virtual"),
				enable: self.scope.get("enable"),
				id: self.scope.get("id"),
				name: self.scope.get("name"),
			});
		});

		if(!virtual) {
			self.scope.set("$satip", isSatIp);
			form.checkbox("SAT>IP", "$satip").on("change", function() {
				if(this.checked) {
					self.scope.set("adapter");
					self.scope.set("device");
					self.scope.set("mac");
					self.scope.set("satip", "");
				} else {
					self.scope.set("satip");
					self.scope.set("satip_pids");
				}
				self.scope.reset();
			});
		}

		if(virtual == "ci") {
			form.input("Adapter", "adapter", "Adapter Number").setRequired(true);
			form.input("Stream ID", "stream").setRequired(true);
			form.input("CI Device", "device", "CI Device number. Default: 0");
			form.input("CI Bitrate", "ci_bitrate", "TBS CI bitrate in MBit/s. Default: 70");
			form.input("CA Delay", "ca_pmt_delay", "Delay before initialize CA module. Default: 20 sec");
		} else if(virtual == "mpts") {
			form.input("Address", "address", "MPTS Stream Address").setRequired(true);
		} else if(isSatIp || virtual == "satip") {
			form.input("SAT>IP Server", "satip", "http://host:port or rtsp://host:port").setRequired(true).addValidator(validateUrl);
			form.input("Adapter", "adapter", "Adapter Number").setRequired(true);
		} else {
			if(self.scope.get("$adapter") == undefined) {
				var a = Number(self.scope.get("adapter"));
				var d = Number(self.scope.get("device") || 0);
				var m = self.scope.get("mac");
				if(!isNaN(a) && !isNaN(d)) {
					self.scope.set(
						"$adapter",
						$.forEach(appHost.sysinfo.dvb_list, function(v, k) {
							if(v.adapter == a && v.device == d) return k;
						})
					);
				} else if(m) {
					self.scope.set(
						"$adapter",
						$.forEach(appHost.sysinfo.dvb_list, function(v, k) {
							if(v.mac == m) return k;
						})
					);
				}
			}
			form.choice("Adapter", "$adapter", dvbList).setRequired();
		}

		if(!virtual || virtual == "satip") {
			form.choice("Type", "type", [
				{ value: "" },
				{
					group: "Satellite",
					items: [
						{ label: "DVB-S", value: "S" },
						{ label: "DVB-S2", value: "S2" },
					],
				},
				{
					group: "Terrestrial",
					items: [
						{ label: "DVB-T", value: "T" },
						{ label: "DVB-T2", value: "T2" },
						{ label: "ATSC", value: "ATSC" },
						{ label: "ISDB-T", value: "ISDBT" },
					],
				},
				{
					group: "Cable",
					items: [
						{ label: "DVB-C", value: "C" },
						{ label: "DVB-C (Annex A)", value: "C/A" },
						{ label: "DVB-C (Annex B)", value: "C/B" },
						{ label: "DVB-C (Annex C)", value: "C/C" },
					],
				},
			])
				.setRequired()
				.on("change", function() {
					if(adapterTypeMap[this.value] != adapterTypeBase) {
						self.scope.reset({
							$tab: tabId,
							satip: self.scope.get("satip"),
							virtual: self.scope.get("virtual"),
							enable: self.scope.get("enable"),
							id: self.scope.get("id"),
							type: this.value,
							name: self.scope.get("name"),
							$adapter: self.scope.get("$adapter"),
						});
					} else {
						self.scope.reset();
					}
				});
		}
	}
	if(adapterType && tabId == "advanced") {
		form.checkbox("Enable monitoring", "no_event")
			.addAttr("data-true", "undefined")
			.addAttr("data-false", "true");
		form.choice("Modulation", "modulation", [
			{ value: "", label: "Default: Auto" },
			{ value: "QPSK" },
			{ value: "QAM16", label: "16-QAM" },
			{ value: "QAM32", label: "32-QAM" },
			{ value: "QAM64", label: "64-QAM" },
			{ value: "QAM128", label: "128-QAM" },
			{ value: "QAM256", label: "256-QAM" },
			{ value: "VSB8" },
			{ value: "VSB16" },
			{ value: "PSK8", label: "8PSK" },
			{ value: "APSK16" },
			{ value: "APSK32" },
			{ value: "DQPSK" },
			{ value: "APSK64" },
			{ value: "APSK128" },
			{ value: "APSK256" },
		]);
	}
	if(adapterTypeBase == "S") {
		if(tabId == "") {
			form.header("Transponder");
			form.number("Frequency", "frequency", "950..40000 MHz")
				.setRequired()
				.addValidator(function(value) {
					value = Number(value);
					return !isNaN(value) && value >= 950 && value < 40000;
				});
			form.choice("Polarization", "polarization", dvbPolarization).setRequired();
			form.number("Symbolrate", "symbolrate", "1000..50000 Kbaud")
				.setRequired()
				.addValidator(function(value) {
					value = Number(value);
					return !isNaN(value) && value > 1e3 && value < 5e4;
				});
		}
		if(tabId == "advanced") {
			form.choice("FEC", "fec", dvbFec);
			if(adapterType == "S2") {
				form.choice("Roll-off", "rolloff", [
					{ value: "", label: "Default: 35" },
					{ value: "25" },
					{ value: "20" },
					{ value: "AUTO" },
				]);
			}
			form.number("Stream ID", "stream_id", "Multistream filtering").addButton(
				$.element
					.button()
					.addClass("icon icon-settings")
					.on("click", function() {
						var x = self.scope.get("stream_id") || 0;
						$.modal()
							.bindScope(AdaptersModule.renderPlsCals, {
								mode: x >> 26,
								code: (x >> 8) & 262143,
								id: x & 255,
							})
							.on("submit", function() {
								var data = this.scope.serialize();
								var streamId = (Number(data.mode) << 26) + (Number(data.code) << 8) + Number(data.id);
								self.scope.set("stream_id", streamId > 0 ? streamId : undefined);
							});
					})
			);
		}
		if(tabId == "lnb") {
			form.number("LOF1", "lof1", "Low sub-band");
			form.number("LOF2", "lof2", "High sub-band");
			form.number("SLOF", "slof", "Sub-band range");
			var lnbMode = "";
			if(self.scope.get("lnb_sharing")) {
				lnbMode = "lnb_sharing";
			} else if(self.scope.get("diseqc") != undefined) {
				switch(self.scope.get("diseqc_mode")) {
					case "1.1":
						lnbMode = "diseqc_11";
						break;
					case "toneburst":
						lnbMode = "toneburst";
						break;
					case "cmd":
						lnbMode = "diseqc_cmd";
						break;
					default:
						lnbMode = "diseqc_10";
						break;
				}
			} else if(self.scope.get("uni_scr") != undefined) {
				switch(self.scope.get("uni_mode")) {
					case "2":
						lnbMode = "unicable_20";
						break;
					default:
						lnbMode = "unicable_10";
						break;
				}
				if(self.scope.get("uni_pos") == "A") self.scope.set("uni_pos");
			}
			self.scope.set("$lnb_mode", lnbMode);
			form.checkbox("Force Tone", "tone");
			form.choice("LNB Mode", "$lnb_mode", [
				{ value: "", label: "Auto (Default)" },
				{ value: "lnb_sharing", label: "LNB Sharing" },
				{ value: "diseqc_10", label: "DiSEqC 1.0" },
				{ value: "diseqc_11", label: "DiSEqC 1.1" },
				{ value: "diseqc_cmd", label: "DiSEqC Command" },
				{ value: "toneburst", label: "Tone Burst" },
				{ value: "unicable_10", label: "Unicable I (EN50494)" },
				{ value: "unicable_20", label: "Unicable II (EN50607)" },
			]).on("change", function() {
				self.scope.set("uni_scr");
				self.scope.set("uni_pos");
				self.scope.set("uni_frequency");
				self.scope.set("diseqc_mode");
				self.scope.set("diseqc");
				self.scope.set("lnb_sharing");
				if(this.value == "lnb_sharing") {
					self.scope.set("lnb_sharing", true);
				} else if(this.value == "toneburst") {
					self.scope.set("diseqc_mode", "toneburst");
					self.scope.set("diseqc", "");
				} else if(this.value == "diseqc_10") {
					self.scope.set("diseqc", "");
				} else if(this.value == "diseqc_11") {
					self.scope.set("diseqc_mode", "1.1");
					self.scope.set("diseqc", "");
				} else if(this.value == "diseqc_cmd") {
					self.scope.set("diseqc_mode", "cmd");
					self.scope.set("diseqc", "");
				} else if(this.value == "unicable_10") {
					self.scope.set("uni_mode");
					self.scope.set("uni_scr", "");
				} else if(this.value == "unicable_20") {
					self.scope.set("uni_mode", "2");
					self.scope.set("uni_scr", "");
				}
				self.scope.reset();
			});
			if(!lnbMode || lnbMode == "lnb_sharing") {
			} else if(lnbMode == "diseqc_10") {
				var x = [{ value: "" }];
				for(var i = 1; i <= 4; i++) {
					x.push({ value: i });
				}
				form.choice("DiSEqC 1.0", "diseqc", x).setRequired(true);
			} else if(lnbMode == "diseqc_11") {
				var x = [{ value: "" }];
				for(var i = 1; i <= 16; i++) {
					x.push({ value: i });
				}
				form.choice("DiSEqC 1.1", "diseqc", x).setRequired(true);
			} else if(lnbMode == "diseqc_cmd") {
				form.input("DiSEqC Command", "diseqc").setRequired(true);
			} else if(lnbMode == "toneburst") {
				form.choice("Tone Burst", "diseqc", [
					{ value: "" },
					{ value: "A" },
					{ value: "B" },
				]).setRequired(true);
			} else if(lnbMode == "unicable_10") {
				var uniChId = [];
				for(var i = 1; i <= 8; ++i) {
					uniChId.push({ value: i });
				}
				form.choice("Unicable Slot", "uni_scr", uniChId).setRequired(true);
				form.choice("Slot Position", "uni_pos", [
					{ value: "", label: "Default: A" },
					{ value: "B" },
				]);
				form.number("Slot Frequency", "uni_frequency", "950..2150 MHz")
					.setRequired(true)
					.addValidator(function(value) {
						if(value == undefined || value == "") return true;
						value = Number(value);
						return !isNaN(value) && value >= 950 && value < 2150;
					});
			} else if(lnbMode == "unicable_20") {
				var uniChId = [];
				for(var i = 1; i <= 32; ++i) {
					uniChId.push({ value: i });
				}
				form.choice("Unicable Slot", "uni_scr", uniChId).setRequired(true);
				form.choice("Slot Position", "uni_pos", [
					{ value: "", label: "Default: A" },
					{ value: "B" },
					{ value: "C" },
					{ value: "D" },
				]);
				form.number("Slot Frequency", "uni_frequency", "950..2150 MHz")
					.setRequired(true)
					.addValidator(function(value) {
						if(value == undefined || value == "") return true;
						value = Number(value);
						return !isNaN(value) && value >= 950 && value < 2150;
					});
			}
		}
	} else if(adapterTypeBase == "T") {
		if(tabId == "") {
			form.number("Frequency", "frequency", "1..1000 MHz")
				.setRequired()
				.addValidator(function(value) {
					value = Number(value);
					return !isNaN(value) && ((value > 0 && value < 1e3) || (value > 1e6 && value < 1e9));
				});
		}
		if(tabId == "advanced") {
			form.number("PLP ID", "stream_id", "Multistream filtering");
			form.choice("Bandwidth", "bandwidth", [
				{ value: "", label: "Default: Auto" },
				{ value: "6MHz" },
				{ value: "7MHz" },
				{ value: "8MHz" },
			]);
			form.choice("Guard", "guardinterval", [
				{ value: "", label: "Default: Auto" },
				{ value: "1/32" },
				{ value: "1/16" },
				{ value: "1/8" },
				{ value: "1/4" },
				{ value: "1/128" },
				{ value: "19/128" },
				{ value: "19/256" },
				{ value: "PN420" },
				{ value: "PN595" },
				{ value: "PN945" },
			]);
			form.choice("Transmit", "transmitmode", [
				{ value: "", label: "Default: Auto" },
				{ value: "1K" },
				{ value: "2K" },
				{ value: "4K" },
				{ value: "8K" },
				{ value: "16K" },
				{ value: "32K" },
			]);
			form.choice("Hierarchy", "hierarchy", [
				{ value: "", label: "Default: Auto" },
				{ value: "NONE" },
				{ value: "1" },
				{ value: "2" },
				{ value: "4" },
			]);
		}
	} else if(adapterTypeBase == "C") {
		if(tabId == "") {
			form.number("Frequency", "frequency", "80..1000 MHz")
				.setRequired()
				.addValidator(function(value) {
					value = Number(value);
					return !isNaN(value) && ((value >= 80 && value < 1e3) || (value >= 8e7 && value < 1e9));
				});
			form.number("Symbolrate", "symbolrate", "1000..10000 Kbaud")
				.setRequired()
				.addValidator(function(value) {
					value = Number(value);
					return !isNaN(value) && value > 1e3 && value < 1e4;
				});
		}
		if(tabId == "advanced") {
			form.choice("FEC", "fec", dvbFec);
		}
	} else if(adapterTypeBase == "ATSC") {
		if(tabId == "") {
			form.number("Frequency", "frequency", "0..1000 MHz")
				.setRequired()
				.addValidator(function(value) {
					value = Number(value);
					return !isNaN(value) && ((value > 0 && value < 1e3) || (value > 1e6 && value < 1e9));
				});
		}
	} else if(adapterTypeBase == "ISDBT") {
		if(tabId == "") {
			form.number("Frequency", "frequency", "0..1000 MHz")
				.setRequired()
				.addValidator(function(value) {
					value = Number(value);
					return !isNaN(value) && ((value > 0 && value < 1e3) || (value > 1e6 && value < 1e9));
				});
		}
		if(tabId == "advanced") {
			form.choice("Bandwidth", "bandwidth", [
				{ value: "", label: "Default: Auto" },
				{ value: "6MHz" },
				{ value: "7MHz" },
				{ value: "8MHz" },
			]);
		}
	}
	if(adapterType && tabId == "advanced") {
		form.input("Timeout", "timeout", "Delay in seconds before check DVR errors. Default: 120 sec");
		form.input("DDCI", "ddci", "Bind adapter to the DigitalDevices CI (deprecated. use CI)");
		form.input("CI", "ci", "Bind adapter to the DigitalDevices or TBS CI");
		form.input("CI Device", "ci_device", "CI device number. Default: 0");
		form.input("CI Bitrate", "ci_bitrate", "TBS CI bitrate in MBit/s. Default: 70");
		form.input("FE Device", "fe_device", "FE device number. Default: 0");
		form.input("BISS", "biss", "Descramble an entire transponder").addValidator(validateBiss);
		form.checkbox("DVB API v3", "dvbapi3");
		form.checkbox("Budget Mode. Disable hardware PID filtering", "budget");
		form.input("CA Delay", "ca_pmt_delay", "Delay before initialize CA module. Default: 20 sec");
		if(isSatIp) form.input("SAT>IP Pids", "satip_pids", "Default: all");
	}
	var serialize = function() {
		if(self.scope.get("$remove")) {
			return { remove: true };
		}
		var data = self.scope.serialize();
		if(!data.id) data.id = appHost.makeUid("dvb_tune");
		if(!data.diseqc) delete data["diseqc_mode"];
		return data;
	};
	var apply = function(streams, cam) {
		if(!isSatIp && !virtual) {
			const adapter = appHost.sysinfo.dvb_list[self.scope.get("$adapter")];
			const settings = appHost.config.settings || {};
			if(settings.dvb_bind_by_mac && adapter.mac) {
				self.scope.set("adapter");
				self.scope.set("device");
				self.scope.set("mac", adapter.mac);
			} else {
				self.scope.set("adapter", adapter.adapter);
				self.scope.set("device", adapter.device);
				self.scope.set("mac");
			}
		}
		var data = serialize();
		$.forEach(streams, function(s) {
			s.enable = true;
			s.type = "spts";
			s.id = appHost.makeUid("make_stream");
			var x = "dvb://" + data.id + "#pnr=" + s.pnr;
			if(cam) x += cam == true ? "&cam" : "&cam=" + cam;
			s.input = [x];
			delete s.pnr;
		});
		appHost.request({
			cmd: "set-adapter",
			gid: appHost.config.gid,
			id: adapterId,
			adapter: data,
			scan: streams,
		}, function() {
			self.remove();
		}, function() {
			$.err({
				title: "Failed to save adapter",
			});
		});
	};

	form.hr();

	var btnApply = $.element
		.button("Apply")
		.addClass(self.scope.get("$remove") ? "danger" : "submit")
		.on("click", function() {
			if(!self.scope.get("$remove") && !self.scope.validate()) {
				$.err({
				title: "Form has errors",
			});
		} else {
			apply();
		}
	});

	var btnScan = $.element.button("Scan").on("click", function() {
		if(!self.scope.validate()) {
			$.err({
				title: "Form has errors",
			});
		} else {
			AdaptersModule.startScan.call(self, hostId, apply);
		}
	});

	if(adapterId != "-" && tabId == "") {
		form.checkbox("Remove", "$remove")
			.setDanger()
			.on("change", function() {
				if(this.checked) btnApply.removeClass("submit").addClass("danger");
				else btnApply.removeClass("danger").addClass("submit");
			});
	}

	var btnCancel = $.element
		.button("Cancel")
		.on("click", function() {
			self.remove();
		});

	form.submit().addChild(
		btnApply,
		btnScan,
		btnCancel
	);
};

AdaptersModule.modal = function(host, aid) {
	var scope;
	if(aid == "-") {
		scope = { "enable": true };
	} else {
		var a = MainModule.adapters[host + "/" + aid];
		if(!a) {
			$.err({ text: "Adapter " + aid + " on " + host + " not found" });
			return;
		}
		scope = $.clone(a.$config);
	}

	$.modal().bindScope(render, scope, host, aid);
};

app.modules.push(AdaptersModule);
})();

/* sessions.js */

(function() {
"use strict";

window.SessionsModule = {
	label: "Sessions",
	link: "#/sessions",
	order: 5,
};

SessionsModule.run = function() {
	SessionsModule.sessions = {};
	SessionsModule.hide = (app.hosts[location.host].config.settings || {}).http_disable_sessions;
	app.on("session_event", function(event) {
		var hostId = event.host,
			data = event.data,
			cdate = Date.now();
		$.forEach(data.sessions, function(e) {
			var sessionsId = hostId + "/" + e.client_id;
			if(e.hasOwnProperty("channel_id")) {
				e.host = hostId;
				e.sdate = new Date(cdate - e.uptime * 1e3);
				if(SessionsModule.addSession) SessionsModule.addSession(e);
				SessionsModule.sessions[sessionsId] = e;
			} else {
				if(SessionsModule.removeSession) SessionsModule.removeSession(sessionsId);
				delete SessionsModule.sessions[sessionsId];
			}
		});
	});
};

SessionsModule.addHost = function(hostId) {
	var appHost = app.hosts[hostId];
	appHost.request({
		cmd: "sessions",
	}, function(response) {
		var cdate = Date.now();
		$.forEach(response.data.sessions, function(e) {
			var sessionsId = hostId + "/" + e.client_id;
			e.host = hostId;
			e.sdate = new Date(cdate - e.uptime * 1e3);
			SessionsModule.sessions[sessionsId] = e;
			if(SessionsModule.addSession) SessionsModule.addSession(e);
		});
	});
};

SessionsModule.removeHost = function(hostId) {
	$.forEach(SessionsModule.sessions, function(s, i) {
		if(s.host == hostId) {
			if(SessionsModule.removeSession) SessionsModule.removeSession(i);
			delete SessionsModule.sessions[i];
		}
	});
};

SessionsModule.render = function() {
	var object = app.renderInit();
	var orderString = function(a, b) {
		var ca = a.textContent;
		var cb = b.textContent;
		return ca.localeCompare(cb);
	};
	var orderNumber = function(a, b) {
		var ca = Number(a.dataset.value);
		var cb = Number(b.dataset.value);
		return ca == cb ? 0 : ca > cb ? 1 : -1;
	};
	var sessionsTotalValue = 0;
	var sessionsTotal = $.element("span").setText(0);
	var total = $.element("p").addAttr("style", "font-weight: bold; padding-left: 5px;").addChild("Total Sessions: ", sessionsTotal);
	var header = $.element("thead").addChild(
		$.element("tr").addChild(
			$.element("th")
				.setText("Server")
				.setStyle("width", "200px")
				.dataOrder(orderString),
			$.element("th")
				.setText("Stream")
				.dataOrder(orderString, true),
			$.element("th")
				.setText("IP")
				.setStyle("width", "150px")
				.dataOrder(orderNumber),
			$.element("th")
				.setText("Login")
				.setStyle("width", "150px")
				.dataOrder(orderString),
			$.element("th")
				.setText("Uptime (hour:min)")
				.setStyle("width", "150px")
				.dataOrder(orderNumber),
			$.element("th")
				.setText("User-Agent")
				.setStyle("width", "150px"),
			$.element("th")
				.setStyle("width", "32px")
		)
	);
	var content = $.element("tbody");
	content.nodes = {};
	var table = $.element("table").addClass("table hover striped").addChild(header, content);
	object.addChild(total, table);
	$.tableInit(table);
	SessionsModule.addSession = function(s) {
		sessionsTotal.setText(++sessionsTotalValue);
		var uptime = $.element("td").addAttr("data-value", s.uptime);
		var hostName = app.hosts[s.host].name;
		var row = $.element("tr").addChild(
			$.element("td").addAttr("data-value", hostName).setText(hostName),
			$.element("td").setText(s.channel_name),
			$.element("td").addAttr("data-value", ip2num(s.addr)).setText(s.addr),
			$.element("td").addChild(
				(s.login != undefined)
					? $.element("a")
						.setText(s.login)
						.on("click", function(event) {
							event.preventDefault();
							SettingsUsersModule.openConfig(s.login);
						})
					: ""
			),
			uptime,
			$.element("td")
				.addClass("nowrap")
				.addAttr("title", s.ua)
				.setText(s.ua),
			$.element("td")
				.addClass("action")
				.addChild(
					$.element
						.button()
						.addClass("icon icon-close")
						.on("click", function() {
							app.hosts[s.host].request({
								cmd: "close-session",
								id: s.client_id,
							});
						})
				)
		);
		row.refreshUptime = function() {
			var c = Date.now(),
				u = c - s.sdate,
				d = Math.round(u / 6e4),
				m = d % 60,
				h = Math.floor(d / 60);
			if(m < 10) m = "0" + m;
			uptime.addAttr("data-value", u).setText(h + ":" + m);
		};
		row.refreshUptime();
		content.nodes[s.host + "/" + s.client_id] = row;
		$.tableSortInsert(table, row);
	};
	SessionsModule.removeSession = function(id) {
		sessionsTotal.setText(--sessionsTotalValue);
		if(content.nodes[id]) {
			content.nodes[id].remove();
			delete content.nodes[id];
		}
	};
	$.forEach(SessionsModule.sessions, function(e) {
		SessionsModule.addSession(e);
	});
	var refresh = setInterval(function() {
		$.forEach(content.nodes, function(r) {
			r.refreshUptime();
		});
	}, 1e4);
	self.on("destroy", function() {
		clearInterval(refresh);
		content.empty();
		content.nodes = {};
		delete SessionsModule.addSession;
		delete SessionsModule.removeSession;
	});
};

SessionsModule.init = function() {
	$.body.bindScope(SessionsModule.render, {});
};

app.modules.push(SessionsModule);
app.menu.push(SessionsModule);
})();

/* settings.js */

(function() {
"use strict";

window.SettingsModule = {
	label: "Settings",
	order: 8,
};

SettingsModule.click = function() {
	var modal = $.modal();
	modal.addClass("main-menu");

	var makeItem = function(item) {
		modal.addChild(
			$.element("a")
				.setText(item.label)
				.addAttr("href", item.link || "#")
				.on("click", function(event) {
					modal.remove();
					if(item.click) {
						event.preventDefault();
						item.click(event);
					}
				})
		);
	};

	var makeItems = function(items) {
		if(items) {
			$.forEach(items, makeItem);
			modal.addChild($.element("hr"));
		}
	};

	makeItems(app.settings);

	modal.addChild(
		$.element("a")
			.setText("Cancel")
			.addClass("text-center")
			.addAttr("href", "#/")
			.on("click", function(event) {
				event.preventDefault();
				modal.remove();
			})
	);
};

app.modules.push(SettingsModule);
app.menu.push(SettingsModule);
})();

/* settings-interface.js */

(function() {
"use strict";

window.SettingsInterfaceModule = {};

function render(appHost, profile) {
	var self = this,
		form = new Form(self.scope, self);

	form.input("Web Interface Name", "title", "Custom name for web interface title")
		.on("input", function() {
			app.setTitle(this.value);
		});
	form.choice("Theme", "theme", app.themes)
		.on("change", function() {
			app.setTheme(this.value);
		});
	form.header("Dashboard");
	var arrangeList = [
		{ value: "", label: "Default: None" },
		{ value: "-", label: "---", disabled: true },
		{ value: "$type", label: "Type" },
		{ value: "$host", label: "Servers" },
		{ value: "$dvb", label: "Adapter" },
		{ value: "-", label: "---", disabled: true },
	];
	$.forEach(appHost.config.categories, function(c) {
		arrangeList.push({ value: c.name });
	});
	form.choice("Arrange By", "arrange", arrangeList);
	form.checkbox("Hide disabled items", "hide_disabled");
	form.checkbox("Hide inactive items", "hide_inactive");
	form.checkbox("Hide items without error", "hide_wo_error");
	var orderList = [
		{ value: "", label: "Default: Type and Name" },
		{ value: "status", label: "Type, Status, and Name" },
		{ value: "lcn", label: "LCN" },
	];
	form.choice("Order By", "order", orderList);

	var serialize = function() {
		var data = self.scope.serialize();
		$.forEach(data, function(v, k) {
			if(!v) delete data[k];
		});
		return (!$.isObjectEmpty(data)) ? data : undefined;
	};

	var btnApply = $.element
		.button("Apply")
		.addClass("submit")
		.on("click", function() {
			profile.interface = serialize();
			appHost.request({
				cmd: "set-user",
				id: app.login,
				user: profile,
			}, function(data) {
				self.remove();
			}, function() {
				$.err({
					title: "Failed to save settings",
				});
			});
		});

	var btnCancel = $.element
		.button("Cancel")
		.on("click", function() {
			self.remove();
		});

	form.submit().addChild(
		btnApply,
		btnCancel
	);
};

SettingsInterfaceModule.modal = function() {
	var appHost = app.hosts[location.host],
		profile = $.clone(appHost.config.users[app.login]) || {},
		scope = $.clone(profile.interface) || {};
	if(profile.cipher) delete profile.cipher;
	if(profile.interface) delete profile.interface;
	$.modal().bindScope(render, scope, appHost, profile);
};

app.modules.push(SettingsInterfaceModule);
})();

/* settings-general.js */

(function () {
"use strict";

var SettingsGeneralModule = {
	label: "General",
	link: "#/settings-general",
	order: 2,
};

SettingsGeneralModule.run = function () {
	app.on("set-settings", function (event) {
		var hostId = event.host,
			data = event.data,
			appHost = app.hosts[hostId];
		if (data.gid) appHost.config.gid = data.gid;
		if (data.settings) appHost.config.settings = data.settings;
		else delete appHost.config.settings;
		$.msg({ title: "Settings saved" });
	});
	app.on("set-config", function (event) {
		var hostId = event.host,
			data = event.data,
			appHost = app.hosts[hostId];
		if (data.data) appHost.config[data.key] = data.data;
		else delete appHost.config[data.key];
		$.msg({ title: "Settings saved" });
	});
};

SettingsGeneralModule.render = function () {
	var self = this,
		object = app.renderInit(),
		masterHost = app.hosts[location.host],
		form = new Form(self.scope, object);
	form.input("Instance Name", "instance_name", "Instance name for monitoring");

	form.input("InfluxDB Address", "tsdb_url", "http://127.0.0.1:8086");
	form.input("InfluxDB Organization", "tsdb_org");
	form.password("InfluxDB Token", "tsdb_token");
	form.input("InfluxDB Interval", "tsdb_interval", "Interval in seconds. Default: 60");
	form.hr();

	form.input("Monitoring", "event_request", "Export telemetry and events to the external server");
	form.hr();

	form.input("HTTP Access Log", "http_access_log", "For example: /var/log/astra-access.log");
	form.checkbox("HTTP Sessions", "http_disable_sessions").addAttr("data-true", "undefined").addAttr("data-false", "true");

	form.input("Sessions backend address", "sessions_url");
	form.number("Minimal session time (seconds)", "sessions_time");
	form.text("Allow real ip header from", "allow_real_ip");
	form.hr();
	form.input("TLS Certificate Chain", "crt_chain", "Full path to certificate chain");
	form.input("TLS Certificate Key", "crt_key", "Full path to certificate private key");
	form.input("Custom port to Web Interface", "control_port");
	form.input("Custom path to Web Interface", "control_path");
	form.input("Custom HTTP Server Name", "http_server_name");
	form.checkbox("Disable TLS on primary port", "http_disable_tls");
	form.header("Default Stream Options");
	form.checkbox("Start stream on demand", "http_keep_active").addAttr("data-true", "undefined").addAttr("data-false", "-1");
	form.number("HTTP Keep Active", "http_keep_active", "Delay before stop stream if no active connections. Default: 0 (turn off immediately)");
	form.number("Backup Start Delay", "backup_start_delay", "Delay before start next input. Default: 5");
	form.number("Backup Return Delay", "backup_return_delay", "Delay before return to previous input. Default: 30");
	form.choice("Default Codepage", "textcode", codepages);
	form.input("Service Provider", "service_provider", "Provider name for service description (SDT)");
	form.input("Network Name", "network_name", "Network name for network information (NIT)");
	form.input("TCP Congestion Control", "http_congestion");
	form.number("CC Limit", "cc_limit", "Default: 0 (not limited)");
	form.checkbox("Use multithreading for UDP receiving and transmitting", "udp_threads");
	form.checkbox("Bind DVB adapters by MAC", "dvb_bind_by_mac");
	var btnApply = $.element
		.button("Apply & Restart")
		.addClass("submit")
		.on("click", function () {
			masterHost.request(
				{ cmd: "set-settings", settings: self.scope.serialize() },
				function (data) {},
				function () {
					$.err({ title: "Failed to save settings" });
				}
			);
		});
	form.submit().addChild(btnApply);
};

SettingsGeneralModule.init = function () {
	var h = app.hosts[location.host];
	var s = $.clone(h.config.settings) || {};
	$.body.bindScope(SettingsGeneralModule.render, s);
};

app.modules.push(SettingsGeneralModule);
app.settings.push(SettingsGeneralModule);
})();

/* settings-users.js */

(function () {
"use strict";

window.SettingsUsersModule = {
	label: "Users",
	link: "#/settings-users",
	order: 5,
	search: true,
	menu: [
		{
			label: "New User",
			click: function () {
				SettingsUsersModule.openConfig();
			},
		},
	],
};

SettingsUsersModule.typeMap = { 3: "User", 2: "Observer", 1: "Administrator" };

SettingsUsersModule.modules = [];

SettingsUsersModule.run = function () {
	app.on("set-user", function (event) {
		var hostId = event.host,
			data = event.data,
			appHost = app.hosts[hostId];
		if (data.id == app.login) {
			location.reload(false);
			return;
		}
		if (data.user.remove) {
			$.msg({ title: 'User "{0}" removed'.format(data.id) });
			delete appHost.config.users[data.id];
			if (SettingsUsersModule.removeUser) {
				SettingsUsersModule.removeUser(data.id);
			}
		} else {
			appHost.config.users[data.id] = data.user;
			$.msg({ title: 'User "{0}" saved'.format(data.id) });
			if (SettingsUsersModule.addUser) {
				SettingsUsersModule.removeUser(data.id);
				SettingsUsersModule.addUser(data.id, data.user);
			}
		}
	});
};

var value2date = function (v) {
	if (!v) return "";
	var d = new Date(v * 1e3);
	var dd = ("0" + d.getDate()).slice(-2);
	var dm = ("0" + (d.getMonth() + 1)).slice(-2);
	var dy = d.getFullYear();
	return dy + "-" + dm + "-" + dd;
};

var daysInMonth = function (date) {
	return new Date(date.getYear(), date.getMonth() + 1, 0).getDate();
};

var daysInYear = function (date) {
	date = date.getYear() + 1900;
	return (date % 4 == 0 && date % 100 != 0) || (date % 4 == 0 && date % 100 == 0 && date % 400 == 0) ? 366 : 365;
};

var addDays = function (date, v) {
	var x = new Date(date);
	switch (v) {
		case "1d":
			v = 1;
			break;
		case "1w":
			v = 7;
			break;
		case "1m": {
			v = daysInMonth(date);
			var next = new Date(date.getYear(), date.getMonth() + 1, 1);
			next = daysInMonth(next);
			if (date.getDate() > next) v = v - date.getDate() + next;
			break;
		}
		case "1y":
			v = daysInYear(date);
			break;
		default:
			v = 0;
	}
	x.setDate(date.getDate() + v);
	return x;
};

SettingsUsersModule.renderConfig = function () {
	var modal = this,
		form = new Form(modal.scope, modal),
		login = modal.scope.get("login"),
		appHost = app.hosts[location.host];
	if (app.login != login) {
		form.checkbox("Enable", "user.enable").addAttr("data-false", "false");
	}
	var inputLogin = form.input("Login", "login");
	var inputPass = form.password("Password", "user.password");
	if (login) {
		inputLogin.setDisabled(true);
		if (modal.scope.get("user.firstrun")) {
			inputPass.setRequired();
			modal.scope.set("user.firstrun");
		}
	} else {
		inputLogin.setRequired().addValidator(function (value) {
			if (value == login) return true;
			return appHost.config.users[value] == undefined;
		});
	}
	form.input("Comment", "user.comment");
	if (app.login != login) {
		var typeMap = [];
		$.forEach(SettingsUsersModule.typeMap, function (label, value) {
			typeMap.push({ value: value, label: label });
		});
		typeMap.sort(function (a, b) {
			return a.label.localeCompare(b.label);
		});
		form.choice("Type", "user.type", typeMap);
	}
	var auth_enable = appHost.config.auth && !!appHost.config.auth.enable;
	if (auth_enable) {
		form.input("Token", "user.token");
		form.input("IP", "user.ip");
		var d = form.scope.get("user.expire");
		if (d) form.scope.set("$user-expire", value2date(d));
		form.input("Expiration", "$user-expire", "Format: YYYY-MM-DD")
			.on("input", function () {
				var x = this.value || "0";
				x = x.split("-");
				if (x.length != 3) {
					x = undefined;
				} else {
					x = new Date(Number(x[0]), Number(x[1]) - 1, Number(x[2]));
					x = x.getTime() / 1e3;
				}
				form.scope.set("user.expire", x);
			})
			.addButton(
				$.element("select")
					.addClass("button icon icon-more")
					.on("change", function () {
						var x = form.scope.get("user.expire");
						x = !!x ? new Date(x * 1e3) : new Date();
						x = addDays(x, this.value);
						x = x.getTime() / 1e3;
						form.scope.set("user.expire", x);
						form.scope.set("$user-expire", value2date(x));
						this.value = "";
					})
					.addChild($.element("option"))
					.addChild($.element("option").setValue("1d").setText("+1 Day"))
					.addChild($.element("option").setValue("1w").setText("+1 Week"))
					.addChild($.element("option").setValue("1m").setText("+1 Month"))
					.addChild($.element("option").setValue("1y").setText("+1 Year"))
			);
		form.input("Limit connections", "user.conlimit", "Default: 0 - unlimited");
		var categoriesMap = [{ value: "" }];
		$.forEach(app.hosts[location.host].config.categories, function (x) {
			categoriesMap.push({ value: x.name });
		});
		categoriesMap.sort(function (a, b) {
			return a.value.localeCompare(b.value);
		});
		var packages = form.scope.get("user.packages");
		form.header("Packages", "New Package", function () {
			if (!packages) {
				packages = [];
				form.scope.set("user.packages", packages);
			}
			packages.push("");
			form.scope.reset();
		});
		$.forEach(packages, function (v, k) {
			form.choice("", "user.packages." + k, categoriesMap).on("change", function () {
				if (!this.value) {
					packages.splice(k, 1);
					if (!packages.length) form.scope.set("user.packages");
					form.scope.reset();
				}
			});
		});
	}
	$.forEach(SettingsUsersModule.modules, function (module) {
		form.hr();
		module.renderSettings.call(modal, form);
	});
	form.hr();
	var btnApply = $.element
		.button("Apply")
		.addClass("submit")
		.on("click", function () {
			if (modal.scope.validate()) modal.submit();
		});
	var btnCancel = $.element.button("Cancel").on("click", function () {
		modal.remove();
	});
	if (login && app.login != login)
		form.checkbox("Remove user", "user.remove")
			.setDanger()
			.on("change", function () {
				if (this.checked) btnApply.removeClass("submit").addClass("danger");
				else btnApply.removeClass("danger").addClass("submit");
			});
	form.submit().addChild(btnApply, btnCancel);
};

SettingsUsersModule.openConfig = function (login) {
	var modalData = {};
	if (login == undefined) {
		modalData.login = "";
		modalData.user = { enable: true, type: 3 };
	} else {
		modalData.login = login;
		modalData.user = $.clone(app.hosts[location.host].config.users[login]);
	}
	$.modal()
		.bindScope(SettingsUsersModule.renderConfig, modalData)
		.on("submit", function () {
			var data = this.scope.serialize();
			if (data.user.remove) data.user = { remove: true };
			var appHost = app.hosts[location.host];
			appHost.request(
				{ cmd: "set-user", id: data.login, user: data.user },
				function () {},
				function () {
					$.err({ title: "Failed to save user" });
				}
			);
		});
};

SettingsUsersModule.render = function () {
	var self = this,
		object = app.renderInit(),
		appHost = app.hosts[location.host];
	var orderString = function (a, b) {
		var ca = a.innerHTML;
		var cb = b.innerHTML;
		return ca.localeCompare(cb);
	};
	var orderNumber = function (a, b) {
		var ca = Number(a.dataset.value);
		var cb = Number(b.dataset.value);
		return ca == cb ? 0 : ca > cb ? 1 : -1;
	};
	var header = $.element("thead").addChild(
		$.element("tr").addChild(
			$.element("th").setText("Login").setStyle("width", "200px").dataOrder(orderString, true),
			$.element("th").setText("Comment").addClass("expand").dataOrder(orderString),
			$.element("th").setText("Type").setStyle("width", "150px").dataOrder(orderNumber),
			$.element("th").setText("Created").setStyle("width", "150px").dataOrder(orderNumber)
		)
	);
	var auth_enable = appHost.config.auth && !!appHost.config.auth.enable;
	if (auth_enable) {
		header.firstChild.addChild(
			$.element("th").setText("IP").setStyle("width", "150px").addAttr("data-order", "on").dataOrder(orderNumber),
			$.element("th").setText("Expiration").setStyle("width", "150px").addAttr("data-order", "on").dataOrder(orderNumber)
		);
	}
	$.forEach(SettingsUsersModule.modules, function (module) {
		if (module.renderHeader) module.renderHeader(header.firstChild);
	});
	var content = $.element("tbody");
	content.nodes = {};
	var table = $.element("table").addClass("table hover").addChild(header, content);
	object.addChild(table);
	$.tableInit(table);
	SettingsUsersModule.addUser = function (login, u) {
		var row = $.element("tr")
			.addChild(
				$.element("td").setText(login),
				$.element("td").setText(u.comment || ""),
				$.element("td").addAttr("data-value", u.type).setText(SettingsUsersModule.typeMap[u.type]),
				$.element("td").addAttr("data-value", u.created).setText(time2ddmmmyyyy(u.created))
			)
			.on("click", function () {
				SettingsUsersModule.openConfig(login);
			});
		if (auth_enable) {
			row.addChild($.element("td").addAttr("data-value", ip2num(u.ip)).setText(u.ip), $.element("td").addAttr("data-value", u.expire).setText(time2ddmmmyyyy(u.expire)));
		}
		$.forEach(SettingsUsersModule.modules, function (module) {
			if (module.renderItem) module.renderItem(row, u);
		});
		if (u.enable == undefined) u.enable = true;
		if (!u.enable) row.addClass("text-delete text-gray");
		content.nodes[login] = row;
		$.tableSortInsert(table, row);
	};
	SettingsUsersModule.removeUser = function (id) {
		if (content.nodes[id]) {
			content.nodes[id].remove();
			delete content.nodes[id];
		}
	};
	$.forEach(appHost.config.users, function (data, login) {
		SettingsUsersModule.addUser(login, data);
	});
	app.search = function (value) {
		$.tableFilter(content, value.toLowerCase());
	};
	self.on("destroy", function () {
		content.empty();
		content.nodes = {};
		delete SettingsUsersModule.addUser;
		delete SettingsUsersModule.removeUser;
	});
	self.on("ready", function () {
		document.querySelector(".search").focus();
	});
};

SettingsUsersModule.init = function () {
	$.body.bindScope(SettingsUsersModule.render, {});
};

app.modules.push(SettingsUsersModule);
app.settings.push(SettingsUsersModule);
})();

/* settings-hls.js */

(function () {
"use strict";

var SettingsHlsModule = {
	label: "HLS",
	link: "#/settings-hls",
	order: 6,
};

SettingsHlsModule.click = function () {
	app.selectHost(SettingsHlsModule.link);
};

SettingsHlsModule.render = function (hostId) {
	var self = this,
		object = app.renderInit(),
		appHost = app.hosts[hostId],
		form = new Form(self.scope, object);
	form.input("Duration", "duration", "Segments duration in seconds. Default: 3");
	form.input("Quantity", "quantity", "Number of segments. Default: 4");
	form.choice("Segments naming", "naming", [
		{ value: "", label: "Default: PCR hash" },
		{ value: "seq", label: "Sequence" },
	]);

	form.input(
		"Session Timeout",
		"session_timeout",
		"Remove session after defined timeout in seconds. Default: 60"
	);

	form.choice("Resource Path", "path", [
		{ value: "", label: "Default: Absolute" },
		{ value: "relative", label: "Relative" },
		{ value: "full", label: "Full" },
	]);

	form.checkbox("Round duration value", "round_duration");
	form.checkbox("Use Expires header", "expires_header");
	form.checkbox("Pass all data PIDs", "no_filter");
	var defaultHeaders = {
		m3u8: ["Access-Control-Allow-Origin: *", "Access-Control-Allow-Methods: GET", "Access-Control-Allow-Credentials: true", "Content-Type: application/vnd.apple.mpegURL"],
		ts: ["Access-Control-Allow-Origin: *", "Access-Control-Allow-Methods: GET", "Access-Control-Allow-Credentials: true"],
	};
	var makeHeader = function (v) {
		var l = self.scope.get(v + "_headers");
		self.scope.set("$default_" + v + "_headers", !l);
		form.checkbox("Use default headers for ." + v, "$default_" + v + "_headers").on("change", function () {
			var x = this.checked ? undefined : defaultHeaders[v];
			self.scope.set(v + "_headers", x);
			self.scope.reset();
		});
		if (!!l) {
			form.header(v + " Headers", "New Header", function () {
				l.push("");
				self.scope.reset();
				document.querySelector('[name="' + v + "_headers." + (l.length - 1) + '"]').focus();
			});
			$.forEach(l, function (lv, k) {
				form.input("", v + "_headers." + k);
			});
		}
	};
	form.hr();
	makeHeader("m3u8");
	form.hr();

	form.input("TS Extension", "ts_extension", "Default: ts");
	form.input("TS MIME Type", "ts_mime", "Default: video/MP2T");
	makeHeader("ts");
	form.hr();
	var serialize = function () {
		var data = self.scope.serialize();
		$.forEach(["m3u8_headers", "ts_headers"], function (v) {
			var a = data[v];
			if (a) {
				for (var i = 0; i < a.length; ) {
					if (!a[i]) a.splice(i, 1);
					else i++;
				}
				if (!a.length) delete data[v];
			}
		});
		return $.isObjectEmpty(data) ? undefined : data;
	};
	var btnApply = $.element
		.button("Apply & Restart")
		.addClass("submit")
		.on("click", function () {
			appHost.request(
				{ cmd: "set-config", key: "hls", restart: true, data: serialize() },
				function (data) {},
				function () {
					$.err({ title: "Failed to save settings" });
				}
			);
		});
	form.submit().addChild(btnApply);
};

SettingsHlsModule.init = function () {
	var hostId = location.hash.slice(SettingsHlsModule.link.length + 1).split("/");
	if (!hostId || !app.hosts[hostId]) {
		$.route(StreamsModule.link);
		return;
	}
	var s = $.clone(app.hosts[hostId].config.hls) || {};
	$.body.bindScope(SettingsHlsModule.render, s, hostId, 1234, 5678);
};

app.modules.push(SettingsHlsModule);
app.settings.push(SettingsHlsModule);
})();

/* settings-http-play.js */

(function() {
"use strict";

var SettingsHttpPlayModule = {
	label: "HTTP Play",
	link: "#/settings-http-play",
	order: 7,
};

SettingsHttpPlayModule.render = function() {
	var self = this,
		object = app.renderInit(),
		masterHost = app.hosts[location.host],
		form = new Form(self.scope, object);

	var categoriesMap = [{ value: "" }];
	$.forEach(masterHost.config.categories, function(x) {
		categoriesMap.push({ value: x.name });
	});
	categoriesMap.sort(function(a, b) {
		return a.value.localeCompare(b.value);
	});

	var link_m3u8, link_xspf;

	function setLink() {
		const proto = self.scope.get("http_play_disable_tls") ? "http:" : location.protocol;
		const name = self.scope.get("http_play_playlist_name") || "playlist";
		const port = self.scope.get("http_play_port") || location.port;

		const url = proto + "//" + location.hostname + ":" + port + "/" + name;

		link_m3u8.setHtml('<a href="' + url + '.m3u8" target="_blank">' + name + ".m3u8</a>");
		link_xspf.setHtml('<a href="' + url + '.xspf" target="_blank">' + name + ".xspf</a>");
	}

	form.checkbox("Allow HTTP access to all streams", "http_play_stream");
	form.checkbox("Allow HLS access to all streams (disables on-demand feature)", "http_play_hls");
	form.input("HTTP Play Port", "http_play_port", "Custom port for HTTP Play. Default: same as primary port (admin interface)").on("input", setLink);
	form.checkbox("Disable TLS on HTTP Play port", "http_play_disable_tls").on("change", setLink);
	form.input("Path to TV logos", "http_play_tvg_logo");
	form.input("Path to TV screenshots", "http_play_screenshots");
	form.input("Custom name for playlist", "http_play_playlist_name").on("input", setLink);
	form.choice("Playlist Arrange", "playlist_arrange", categoriesMap);
	form.input("HTTP Buffer Size", "http_output_buffer_size", "Maximum buffer size for each client in Kb. Default: 4000");
	form.input("M3U Header", "http_play_m3u_header", "Parameters for M3U playlist");
	form.input("XSPF Playlist Title", "http_play_xspf_title");

	link_m3u8 = form.group();
	link_xspf = form.group();
	setLink();

	form.hr();

	var btnApply = $.element
		.button("Apply & Restart")
		.addClass("submit")
		.on("click", function() {
			masterHost.request({
				cmd: "set-settings",
				settings: self.scope.serialize(),
			}, function(data) {
			}, function() {
				$.err({
					title: "Failed to save settings",
				});
			});
		});

	form.submit().addChild(btnApply);
};

SettingsHttpPlayModule.init = function() {
	var h = app.hosts[location.host];
	var s = $.clone(h.config.settings) || {};
	$.body.bindScope(SettingsHttpPlayModule.render, s);
};

app.modules.push(SettingsHttpPlayModule);
app.settings.push(SettingsHttpPlayModule);
})();

/* settings-http-auth.js */

(function(){"use strict";var SettingsAuthOptionsModule={label:"HTTP Authentication",link:"#/settings-auth",order:9};SettingsAuthOptionsModule.run=function(){app.on("set-auth",function(event){var hostId=event.host,data=event.data,appHost=app.hosts[hostId];if(data.auth)appHost.config.auth=data.auth;else delete appHost.config.auth;$.msg({title:"HTTP Authentication saved"});if(location.hash==SettingsAuthOptionsModule.link)SettingsAuthOptionsModule.init()})};SettingsAuthOptionsModule.render=function(){var self=this,object=app.renderInit(),appHost=app.hosts[location.host],form=new Form(self.scope,object);form.checkbox("Enable built-in HTTP/HLS authentication (restart required)","enable").on("change",function(){self.scope.reset()});var renderList=function(key,title,action){var l=self.scope.get(key);if(!l){l=[];self.scope.set(key,l)}form.header(title,action,function(){l.push("");self.scope.reset();document.querySelector('[name="'+key+"."+(l.length-1)+'"]').focus()});$.forEach(l,function(v,i){var x=form.input("#"+(i+1),key+"."+i);x.on("keydown",function(event){if(event.keyCode==13){event.preventDefault();x.blur();var n;if(event.shiftKey){if(i==0){n=0;l.splice(0,0,"");self.scope.reset()}else{n=i-1}}else{n=i+1;if(n==l.length){l.push("");self.scope.reset()}}document.querySelector('[name="'+key+"."+n+'"]').focus()}});x.addButton($.element.button().addClass("icon icon-close").on("click",function(){l.splice(i,1);if(!l.length)self.scope.set(key);self.scope.reset()}))})};if(self.scope.get("enable")==true){var mwType="";if(self.scope.get("backend")!=undefined){mwType="backend"}else if(self.scope.get("iptvportal")!=undefined){mwType="iptvportal"}else if(self.scope.get("ministra")!=undefined){mwType="ministra"}else if(self.scope.get("smarty")!=undefined){mwType="smarty"}self.scope.set("$mw",mwType);form.choice("Backend Type","$mw",[{value:""},{value:"backend",label:"HTTP Request"},{value:"iptvportal",label:"IPTVPortal"},{value:"smarty",label:"Microimpuls Smarty"},{value:"ministra",label:"Ministra/Stalker"}]).on("change",function(){if(mwType!="")self.scope.set(mwType);if(this.value!="")self.scope.set(this.value,"");self.scope.reset()});if(mwType!=""){form.input("Backend Address",mwType,"http://server:port")}form.checkbox("Allow X-Real-IP","x_real_ip");form.input("Promo Channel","promo","Stream ID for unauthorized clients");form.input("Securetoken","securetoken","Secret key for securetoken");renderList("http_ip_allow","Allow access without authorization","new ip");renderList("http_ip_deny","Block IP address","new ip");renderList("http_token_deny","Block Token","new token")}var serialize=function(){var data=self.scope.serialize();if(!data.enable)return undefined;var cleanList=function(key){var a=data[key];if(a==undefined)return;for(var i=0;i<a.length;){if(!a[i])a.splice(i,1);else++i}if(!a.length)delete data[key]};cleanList("http_ip_allow");cleanList("http_ip_deny");cleanList("http_token_deny");$.forEach(data,function(v,k){if(!v)delete data[k]});return data};var btnApply=$.element.button("Apply").addClass("submit").on("click",function(){appHost.request({cmd:"set-auth",auth:serialize()},function(data){},function(){$.err({title:"Failed to save settings"})})});form.submit().addChild(btnApply)};SettingsAuthOptionsModule.init=function(){var appHost=app.hosts[location.host],scope=appHost.config.auth!=undefined?$.clone(appHost.config.auth):{};$.body.bindScope(SettingsAuthOptionsModule.render,scope)};app.modules.push(SettingsAuthOptionsModule);app.settings.push(SettingsAuthOptionsModule)})();

/* settings-softcam.js */

(function(){
"use strict";

window.SettingsSoftcamModule = {
    label:"Softcam",
    link:"#/settings-softcam",
    order:10
};

SettingsSoftcamModule.click = function(){
    app.selectHost(SettingsSoftcamModule.link, "-")
};

SettingsSoftcamModule.run = function(){
    app.on("set-softcam", function(event) {
        var hostId = event.host,
            appHost = app.hosts[hostId],
            data = event.data;

        if(data.gid) {
            appHost.config.gid = data.gid;
        }

        var sl = appHost.config.softcam;
        var idx = sl == undefined ? -1 : sl.indexOfID(data.softcam.id);

        if(data.softcam.remove && !data.softcam.up) {
            $.msg({
                title: 'Softcam "{0}" removed'.format(sl[idx].name)
            })
        }

        if(idx != -1) {
            sl.splice(idx, 1);
            if(!sl.length) {
                delete(appHost.config.softcam);
            }
        }

        if(!data.softcam.remove) {
            if(!sl) {
                appHost.config.softcam=sl=[];
            }
            sl.push(data.softcam);
            $.msg({
                title: 'Softcam "{0}" saved'.format(data.softcam.name)
            })
        }
    })
};

SettingsSoftcamModule.renderTest = function() {
    var modal = this,
        form = new Form(modal.scope, modal);

    form.input("CaID","caid","Testing...").addAttr("readonly");
    if(modal.scope.get("caid")!=undefined) {
        form.input("AU","au").addAttr("readonly");
        form.input("UA","ua").addAttr("readonly");
        var idents = modal.scope.get("idents");
        if(idents) {
            form.header("Idents");
            $.forEach(idents,function(v, k) {
                form.input(v.id, "idents." + k + ".sa").addAttr("readonly")
            })
        }
    }

    var btnOk = $.element.button("Ok").on("click", function() {
        modal.remove()
    });

    form.hr();
    form.submit().addChild(btnOk)
};

SettingsSoftcamModule.renderStreams = function(hostId, softcamId) {
    var modal = this,
        appHost = app.hosts[hostId],
        form = new Form(modal.scope,modal);
    var streams=[],
        allowedInputs=["dvb","udp","rtp","http"];

    $.forEach(appHost.config.make_stream, function(s) {
        $.forEach(s.input, function(i,k) {
            i=parseUrl(i);
            if(allowedInputs.indexOf(i.format) != -1) {
                streams.push({
                    id: hostId + "/" + s.id,
                    inputId: k,
                    name: s.name + " #" + (k + 1),
                    cam: softcamId === i.cam
                })
            }
        })
    });

    streams.sort(function(a, b) {
        return a.name.localeCompare(b.name)
    });

    $.forEach(streams, function(v) {
        var x = form.checkbox(v.name,"").on("change", function() {
            var s = $.clone(MainModule.streams[v.id].$config),
                i = parseUrl(s.input[v.inputId]);
            if(this.checked) {
                i.cam=softcamId;
            } else {
                delete(i.cam);
            }
            s.input[v.inputId] = makeUrl(i);
            var id = v.id.split("/"),
                streamId = id.pop(),
                hostId = id.pop();
            app.hosts[hostId].request({
                cmd: "set-stream",
                id: streamId,
                stream: s
            }, function(){}, function(){
                $.err({
                    title: "Failed to save stream"
                })
            })
        });

        if(v.cam) {
            x.checked = true
        }
    });

    var btnOk = $.element.button("Ok").addClass("submit").on("click", function() {
        modal.remove()
    });

    form.hr();
    form.submit().addChild(btnOk)
};

SettingsSoftcamModule.render = function(hostId) {
    var self = this,
        object = app.renderInit(),
        softcamId = self.scope.get("$softcamId"),
        appHost = app.hosts[hostId],
        tabId = self.scope.get("$tab") || "",
        form = new Form(self.scope,object),
        type = self.scope.get("type");
    var softcamList = [
        {value: "-", label: "New Softcam"},
        {value: "", label: "---", disabled: true}
    ];
    var softcamSortedList=[];
    $.forEach(appHost.config.softcam, function(i) {
        softcamSortedList.push({
            value: i.id,
            label: i.name
        })
    });
    softcamSortedList.sort(function(a, b) {
        return a.label.localeCompare(b.label)
    });
    softcamList = softcamList.concat(softcamSortedList);
    form.choice("Softcam", "$softcamId", softcamList).on("change", function() {
        if(this.value == "-") {
            app.selectHost(SettingsSoftcamModule.link,"-");
        } else {
            $.route(SettingsSoftcamModule.link + "/" + hostId + "/" + this.value)
        }
    });

    form.hr();
    form.tab("$tab", [
        {label: "General", id: ""},
        {label: "Advanced", id: "advanced"}
    ]);

    if(tabId == "") {
        form.input("Name", "name", "SoftCAM Name").setRequired();
        var x = form.input("ID", "id", "Unique softcam identifier").addValidator(validateId);
        if(softcamId != "-") {
            x.setRequired();
        }
        form.choice("Protocol", "type", [
            {value: "newcamd", label: "NewCAMd"}
        ]);

        if(type == "newcamd") {
            form.input("Address", "host", "Domain or IP Address").setRequired();
            form.number("Port", "port", "Port").setRequired().addValidator(validatePort);
            form.input("Login", "user").setRequired();
            form.password("Password", "pass").setRequired()
        }
    }

    if(tabId == "advanced") {
        if(type == "newcamd") {
            form.input("DES Key", "key", "Default: 0102030405060708091011121314");
            form.input("CaID", "caid", "Change server CaID. Example: 06B0");
            form.number("Timeout", "timeout", "Default: 8 sec.")
        }

        form.input("Shift", "shift", "Input buffer in ms for decryption delay");
        form.checkbox("Make new connection for each input", "split_cam");
        form.checkbox("Allow EMM if allowed by the server", "disable_emm")
            .addAttr("data-true", "undefined")
            .addAttr("data-false", "true");
        form.number("Skip ECM", "skip_ecm", "Ignore first ECM packets")
    }

    var serialize=function() {
        if(self.scope.get("$remove")) {
            return{ remove: true };
        }

        var data = self.scope.serialize();
        if(!data.id) {
            data.id=appHost.makeUid("softcam");
        }
        return data
    };

    form.hr();

    var btnApply = $.element.button("Apply").addClass("submit").on("click", function() {
        if(!self.scope.get("$remove") && !self.scope.validate()) {
            $.err({
                title: "Form has errors"
            });
            return
        }

        var softcam=serialize();
        appHost.request(
            {
                cmd: "set-softcam",
                gid: appHost.config.gid,
                id: softcamId,
                softcam: softcam
            },
            function() {
                if(softcam.remove) {
                    app.selectHost(SettingsSoftcamModule.link, "-")
                } else if(softcamId != softcam.id) {
                    $.route(SettingsSoftcamModule.link + "/" + hostId + "/" + softcam.id)
                } else {
                    self.scope.reset()
                }
            },
            function() {
                $.err({
                    title: "Failed to save softcam"
                })
            }
        )
    });

    var btnTest = $.element.button("Test").on("click", function() {
        if(!self.scope.validate()) {
            $.err({
                title: "Form has errors"
            });
            return
        }
        var modal = $.modal().bindScope(SettingsSoftcamModule.renderTest, {});
        appHost.request(
            {
                cmd: "test-softcam",
                config: serialize()
            },
            function(response) {
                var data = response.data;
                if(data.error) {
                    modal.remove();
                    $.err({
                        title: "Softcam test failed",
                        text: data.error
                    })
                } else {
                    data.info.caid = data.info.caid.toHex(4);
                    data.info.au = data.info.au ? "YES" : "NO";
                    modal.scope.reset(data.info)
                }
            }, function() {
                modal.remove();
                $.err({
                    title: "Softcam test failed"
                })
            }
        )
    });

    var btnClone = $.element.button("Clone").on("click", function() {
        var data = self.scope.serialize();
        data.name = (data.name || "") + " (clone)";
        if(data.id != undefined) {
            delete data.id;
        }
        SettingsSoftcamModule.softcamClone = data;
        app.selectHost(SettingsSoftcamModule.link, "-")
    });

    var btnStreams = $.element.button("Streams").on("click", function() {
        $.modal().bindScope(SettingsSoftcamModule.renderStreams, {}, hostId, softcamId)
    });

    if(softcamId != "-") {
        if(tabId == "") {
            form.checkbox("Remove Softcam","$remove").setDanger().on("change", function () {
                if(this.checked) {
                    btnApply.removeClass("submit").addClass("danger");
                } else {
                    btnApply.removeClass("danger").addClass("submit")
                }
            })
        }
    } else {
        btnClone.setDisabled(true);
        btnStreams.setDisabled(true)
    }

    form.submit().addChild(btnApply, btnTest, btnClone, btnStreams)
};

SettingsSoftcamModule.init = function() {
    var scope,
        x = location.hash.slice(SettingsSoftcamModule.link.length + 1).split("/"),
        softcamId = decodeURIComponent(x.pop()),
        hostId = x.pop(),
        appHost = app.hosts[hostId];

    if(!appHost) {
        $.route(StreamsModule.link);
        return
    }

    if(softcamId == "-") {
        if(SettingsSoftcamModule.softcamClone) {
            scope = SettingsSoftcamModule.softcamClone;
            delete(SettingsSoftcamModule.softcamClone)
        } else {
            scope = {name: "", type: "newcamd" }
        }
    } else {
        var idx = appHost.config.softcam ? appHost.config.softcam.indexOfID(softcamId) : -1;
        if(idx == -1) {
            $.route(SettingsSoftcamModule.link);
            return
        }

        scope = $.clone(appHost.config.softcam[idx])
    }

    scope.$softcamId = softcamId;
    $.body.bindScope(SettingsSoftcamModule.render, scope, hostId)
};

app.modules.push(SettingsSoftcamModule);
app.settings.push(SettingsSoftcamModule)

})();

/* settings-cas.js */

(function(){"use strict";window.SettingsCasModule={label:"CAS",link:"#/settings-cas",order:11};SettingsCasModule.click=function(){app.selectHost(SettingsCasModule.link,"-")};SettingsCasModule.run=function(){app.on("set-cas",function(event){var hostId=event.host,appHost=app.hosts[hostId],data=event.data;if(data.gid)appHost.config.gid=data.gid;var sl=appHost.config.cas;var idx=sl==undefined?-1:sl.indexOfID(data.cas.id);if(data.cas.remove&&!data.cas.up){$.msg({title:'CAS "{0}" removed'.format(sl[idx].name)})}if(idx!=-1){sl.splice(idx,1);if(!sl.length)delete appHost.config.cas}if(!data.cas.remove){if(!sl)appHost.config.cas=sl=[];sl.push(data.cas);$.msg({title:'CAS "{0}" saved'.format(data.cas.name)})}})};SettingsCasModule.render=function(hostId){var self=this,object=app.renderInit(),casId=self.scope.get("$casId"),appHost=app.hosts[hostId],form=new Form(self.scope,object),advanced=self.scope.get("$advanced")==true;var casList=[{value:"-",label:"New CAS"},{value:"",label:"---",disabled:true}];var casSortedList=[];$.forEach(appHost.config.cas,function(i){casSortedList.push({value:i.id,label:i.name})});casSortedList.sort(function(a,b){return a.label.localeCompare(b.label)});casList=casList.concat(casSortedList);form.choice("CAS","$casId",casList).on("change",function(){if(this.value=="-")app.selectHost(SettingsCasModule.link,"-");else $.route(SettingsCasModule.link+"/"+hostId+"/"+this.value)});form.hr();form.input("Name","name","CAS Name").setRequired();form.input("Super CAS ID (hex)","super_cas_id","00000000").setRequired().addValidator(validateHex).addValidator(function(value){return!value||value.length==8});form.checkbox("Start Stream ID with 1","first_stream_id");form.hr();form.input("ECMG Channel ID","ecmg_channel_id").setRequired().addValidator(function(value){if(value==undefined||value=="")return true;value=Number(value);return!isNaN(value)&&value>=0&&value<=65535});form.input("ECMG Address","ecmg_host").setRequired();form.input("ECMG Port","ecmg_port").setRequired().addValidator(validatePort);form.input("Crypto Period","ecmg_cp").setRequired();form.hr();form.choice("EMMG Protocol","emmg_protocol",[{value:"",label:"Default: TCP"},{value:"udp",label:"UDP",disabled:true}]);form.number("EMMG Port","emmg_port").addValidator(validatePort);form.number("EMM PID","emm_pid").setRequired().addValidator(validatePid);form.input("EMM Private Data (hex)","emm_data").addValidator(validateHex);form.checkbox("EMM Clone (duplicate EMM packets to all streams)","emm_clone");form.hr();var serialize=function(){if(self.scope.get("$remove"))return{remove:true};var data=self.scope.serialize();if(!data.id)data.id=appHost.makeUid("cas");return data};var btnApply=$.element.button("Apply").addClass("submit").on("click",function(){if(!self.scope.get("$remove")&&!self.scope.validate()){$.err({title:"Form has errors"});return}var cas=serialize();appHost.request({cmd:"set-cas",gid:appHost.config.gid,id:casId,cas:cas},function(){if(cas.remove){app.selectHost(SettingsCasModule.link,"-")}else if(casId!=cas.id){$.route(SettingsCasModule.link+"/"+hostId+"/"+cas.id)}else{self.scope.reset()}},function(){$.err({title:"Failed to save CAS"})})});var btnClone=$.element.button("Clone").on("click",function(){var data=self.scope.serialize();data.name=(data.name||"")+" (clone)";if(data.id!=undefined)delete data.id;SettingsCasModule.casClone=data;app.selectHost(SettingsCasModule.link,"-")});if(casId!="-"){form.checkbox("Remove","$remove").setDanger().on("change",function(){if(this.checked)btnApply.removeClass("submit").addClass("danger");else btnApply.removeClass("danger").addClass("submit")})}else{btnClone.setDisabled(true)}form.submit().addChild(btnApply,btnClone)};SettingsCasModule.init=function(){var scope,x=location.hash.slice(SettingsCasModule.link.length+1).split("/"),casId=decodeURIComponent(x.pop()),hostId=x.pop(),appHost=app.hosts[hostId];if(!appHost){$.route(StreamsModule.link);return}if(casId=="-"){if(SettingsCasModule.casClone){scope=SettingsCasModule.casClone;delete SettingsCasModule.casClone}else{scope={name:""}}}else{var idx=appHost.config.cas?appHost.config.cas.indexOfID(casId):-1;if(idx==-1){$.route(SettingsCasModule.link);return}scope=$.clone(appHost.config.cas[idx])}scope.$casId=casId;$.body.bindScope(SettingsCasModule.render,scope,hostId)};app.modules.push(SettingsCasModule);app.settings.push(SettingsCasModule)})();

/* settings-groups.js */

(function(){"use strict";window.SettingsGroupsModule={label:"Groups",link:"#/settings-groups",order:20};SettingsGroupsModule.run=function(){app.on("set-category",function(event){var masterHost=app.hosts[location.host],data=event.data;if(data.category.remove){var n=masterHost.config.categories[data.id].name;$.msg({title:'Category "{0}" removed'.format(n)});masterHost.config.categories.splice(data.id,1);if(!masterHost.config.categories.length)delete masterHost.config.categories}else{if(data.id!=undefined){masterHost.config.categories[data.id]=data.category}else{if(!masterHost.config.categories)masterHost.config.categories=[];masterHost.config.categories.push(data.category)}$.msg({title:'Category "{0}" saved'.format(data.category.name)})}})};SettingsGroupsModule.renderStreams=function(){var modal=this,form=new Form(modal.scope,modal),category=modal.scope.get("category"),group=modal.scope.get("group");if(group=="")group=undefined;form.header(category);form.choice("","group",modal.scope.get("groups")).on("change",function(){modal.scope.reset()});form.hr();var streams=[];$.forEach(MainModule.streams,function(v,k){var g;if(v.$config.groups)g=v.$config.groups[category];streams.push({id:k,name:v.$config.name,group:g==group})});streams.sort(function(a,b){return a.name.localeCompare(b.name)});$.forEach(streams,function(v){var x=form.checkbox(v.name,"");if(v.group)x.checked=true;x.on("change",function(){var s=$.clone(MainModule.streams[v.id].$config);if(this.checked==false){if(!group){this.checked=true;return}else{delete s.groups[category];if($.isObjectEmpty(s.groups))delete s.groups}}else{if(!group){delete s.groups[category];if($.isObjectEmpty(s.groups))delete s.groups}else{if(!s.groups)s.groups={};s.groups[category]=group}}var id=v.id.split("/"),streamId=id.pop(),hostId=id.pop(),appHost=app.hosts[hostId];appHost.request({cmd:"set-stream",id:streamId,stream:s},function(){},function(){$.err({title:"Failed to save stream"})})})});var btnOk=$.element.button("Ok").addClass("submit").on("click",function(){modal.remove()});form.hr();form.submit().addChild(btnOk)};SettingsGroupsModule.render=function(){var self=this,object=app.renderInit(),categoryId=self.scope.get("$categoryId"),masterHost=app.hosts[location.host],form=new Form(self.scope,object);var categoriesList=[{value:"-",label:"New Category"},{value:"",label:"---",disabled:true}];var categoriesSortedList=[];$.forEach(masterHost.config.categories,function(i,k){categoriesSortedList.push({value:k,label:i.name})});categoriesSortedList.sort(function(a,b){return a.label.localeCompare(b.label)});categoriesList=categoriesList.concat(categoriesSortedList);form.choice("Category","$categoryId",categoriesList).on("change",function(){$.route(SettingsGroupsModule.link+"/"+this.value)});form.hr();form.input("Name","name","Category Name").setRequired();var groups=self.scope.get("groups");if(!groups){groups=[];self.scope.set("groups",groups)}form.header("Groups","Add Group",function(){groups.push({name:""});self.scope.reset();document.querySelector('[name="groups.'+(groups.length-1)+'.name"]').focus()});$.forEach(groups,function(v,k){if(v.name==undefined)return;var s=$.element("select").addClass("button icon icon-move").on("change",function(){if(this.value=="-1")delete groups[k].name;else groups.move(k,Number(this.value));self.scope.reset()});for(var j=0;j<groups.length;++j)s.addChild($.element("option").setValue(j.toString()).setText(j+1));s.addChild($.element("option").setDisabled(true).setText("---"),$.element("option").setValue("-1").setText("Remove"));s.value=k.toString();form.input(k+1,"groups."+k+".name","Group Name").addButton(s).on("keydown",function(){if(event.keyCode==13){event.preventDefault();var n=k+1;if(n==groups.length){groups.push({name:""});self.scope.reset()}document.querySelector('[name="groups.'+n+'.name"]').focus()}})});form.hr();var serialize=function(){if(self.scope.get("$remove"))return{remove:true};var data=self.scope.serialize();$.forEach(data.groups,function(g){if(!g.name){g.remove=true;delete g.name}});return data};var btnApply=$.element.button("Apply").addClass("submit").on("click",function(){var category=serialize();masterHost.request({cmd:"set-category",id:categoryId!="-"?categoryId:undefined,category:category},function(data){if(category.remove){$.route(SettingsGroupsModule.link)}else if(categoryId=="-"){var i=masterHost.config.categories.length-1;$.route(SettingsGroupsModule.link+"/"+i)}else{self.scope.reset()}},function(){$.err({title:"Failed to save category"})})});var btnStreams=$.element.button("Streams").setDisabled(true).on("click",function(){var category=masterHost.config.categories[categoryId];var modalData={category:category.name,groups:[{value:"",label:"No Group"},{value:"",label:"---",disabled:true}]};$.forEach(category.groups,function(v){modalData.groups.push({value:v.name})});$.modal().bindScope(SettingsGroupsModule.renderStreams,modalData)});if(categoryId!="-"){btnStreams.setDisabled(false);form.checkbox("Remove Category","$remove").setDanger().on("change",function(){if(this.checked)btnApply.removeClass("submit").addClass("danger");else btnApply.removeClass("danger").addClass("submit")})}form.submit().addChild(btnApply,btnStreams)};SettingsGroupsModule.init=function(){var scope,categoryId=location.hash.slice(SettingsGroupsModule.link.length+1);if(!categoryId){$.route(SettingsGroupsModule.link+"/-");return}if(categoryId=="-"){scope={name:"",groups:[]}}else{var masterHost=app.hosts[location.host];categoryId=Number(categoryId);scope=$.clone(masterHost.config.categories[categoryId]);if(!scope){$.route(SettingsGroupsModule.link);return}if(!scope.groups||!scope.groups.length)scope.groups=[]}scope.$categoryId=categoryId;$.body.bindScope(SettingsGroupsModule.render,scope)};app.modules.push(SettingsGroupsModule);app.settings.push(SettingsGroupsModule)})();

/* settings-servers.js */

(function(){
"use strict";

window.SettingsServersModule={
    label: "Servers",
    link: "#/settings-servers",
    order: 15,
};

SettingsServersModule.run = function() {
    app.on("set-server", function(event) {
        var masterHost = app.hosts[location.host],
            data=event.data;

        if(data.server.remove) {
            var s = masterHost.config.servers[data.id];
            app.removeHost(s);
            $.msg({
                title: 'Server "{0}" removed'.format(s.name)
            });
            masterHost.config.servers.splice(data.id,1);

            if(!masterHost.config.servers.length) {
                delete masterHost.config.servers
            }
        } else {
            if(data.id != undefined) {
                app.removeHost(masterHost.config.servers[data.id]);
                masterHost.config.servers[data.id] = data.server;
            } else {
                if(!masterHost.config.servers) {
                    masterHost.config.servers=[];
                }
                masterHost.config.servers.push(data.server);
            }

            if(data.server.enable!=false) {
                app.addHost(data.server);
            }

            $.msg({
                title: 'Server "{0}" saved'.format(data.server.name)
            })
        }
    })
};

SettingsServersModule.renderTest = function() {
    var modal = this,
        form = new Form(modal.scope,modal);

    form.input("Version","version","Testing...").addAttr("readonly");

    var btnOk = $.element.button("Ok").on("click", function() {
        modal.remove()
    });

    form.hr();
    form.submit().addChild(btnOk)
};

SettingsServersModule.render = function() {
    var self = this,
        object = app.renderInit(),
        serverId = self.scope.get("$serverId"),
        masterHost = app.hosts[location.host],
        form = new Form(self.scope,object);

    var serverHost;

    if(serverId != "-") {
        serverHost = self.scope.get("host") + ":" + self.scope.get("port");
    }

    var serversList = [
        { value: "-", label: "New Server" },
        { value: "", label: "---", disabled: true },
    ];

    var sortedList = []

    $.forEach(masterHost.config.servers, function(s, i) {
        sortedList.push({ value: i, label: s.name })
    });

    sortedList.sort(function(a, b) {
        return a.label.localeCompare(b.label)
    });

    form.choice("Server", "$serverId", sortedList).on("change", function() {
        $.route(SettingsServersModule.link + "/" + this.value)
    });

    form.hr();

    if(self.scope.get("enable") == undefined) {
        self.scope.set("enable",true);
    }
    form.checkbox("Enable", "enable").addAttr("data-false","false");
    form.input("Name", "name", "Server Name").setRequired();
    form.input("Address", "host", "Domain or IP Address").setRequired();
    form.number("Port", "port", "Port").setRequired().addValidator(validatePort);

    var maskPass = function(p) {
        var pm = !p ? "" : new Array(p.length + 1).join("*");
        self.scope.set("$maskPass", pm)
    };

    maskPass(self.scope.get("pass"));

    form.input("Login", "user");
    form.input("Password", "$maskPass")
        .on("focus", function() {
            self.scope.set("$maskPass",
            self.scope.get("pass") || "");
        })
        .on("blur", function() {
            self.scope.set("pass", this.value);
            maskPass(this.value);
        });

    form.hr();

    var serialize = function() {
        if(self.scope.get("$remove")) {
            return{ remove:true };
        } else {
            return self.scope.serialize()
        }
    };

    var btnApply = $.element.button("Apply")
        .addClass("submit")
        .on("click", function() {
            if(!self.scope.get("$remove") && !self.scope.validate()) {
                $.err({ title:"Form has errors" });
                return;
            }

            if(serverHost && app.hosts[serverHost]) {
                app.hosts[serverHost].destroy();
                delete(app.hosts[serverHost]);
            }

            var server = serialize();
            masterHost.request(
                {
                    cmd: "set-server",
                    id: serverId != "-" ? serverId : undefined,
                    server: server,
                },
                function(data) {
                    if(server.remove) {
                        $.route(SettingsServersModule.link);
                    } else if(serverId == "-") {
                        var i = masterHost.config.servers.length - 1;
                        $.route(SettingsServersModule.link + "/" + i);
                    } else {
                        self.scope.reset();
                    }
                },
                function() {
                    $.err({ title: "Failed to save server" });
                }
            );
        });

    var btnTest = $.element.button("Test")
        .on("click", function() {
            if(!self.scope.validate()) {
                $.err({ title: "Form has errors" });
                return;
            }

            var modal = $.modal().bindScope(SettingsServersModule.renderTest, {});
            var data = self.scope.serialize();
            var headers = {};

            if(data.user) {
                var token = data.user;
                if(data.pass) {
                    token += ":" + data.pass;
                }

                headers["Authorization"] = "Basic " + $.base64Encode(token);
            }

            $.http(
                {
                    method: "POST",
                    url: "http://" + data.host + ":" + data.port + "/control/",
                    data: JSON.stringify({ cmd: "version" }),
                    headers: headers,
                },
                function(response) {
                    var data = JSON.parse(response.text);
                    data.version = "Astra " + data.version;
                    modal.scope.reset(data);
                },
                function(response) {
                    modal.remove();
                    $.err({ title: "Failed to test server" });
                }
            );
        });

    if(serverId != "-") {
        form.checkbox("Remove Server", "$remove")
            .setDanger()
            .on("change", function() {
                if(this.checked) {
                    btnApply.removeClass("submit").addClass("danger");
                } else {
                    btnApply.removeClass("danger").addClass("submit");
                }
            });
    }

    form.submit().addChild(btnApply,btnTest);
};

SettingsServersModule.init = function() {
    var scope,
        serverId = location.hash.slice(SettingsServersModule.link.length + 1);

    if(!serverId) {
        $.route(SettingsServersModule.link + "/-");
        return;
    }

    if(serverId == "-") {
        scope = {
            enable: true,
            name: "",
        }
    } else {
        var masterHost = app.hosts[location.host];
        serverId = Number(serverId);
        scope = $.clone(masterHost.config.servers[serverId]);
        if(!scope) {
            $.route(SettingsServersModule.link);
            return;
        }
    }

    scope.$serverId = serverId;
    $.body.bindScope(SettingsServersModule.render,scope)
};

app.modules.push(SettingsServersModule);
app.settings.push(SettingsServersModule)
})();

/* settings-import.js */

(function(){"use strict";var SettingsImportModule={label:"Import",link:"#/settings-import",order:90};SettingsImportModule.click=function(){app.selectHost(SettingsImportModule.link)};var importM3U=function(content){content=content.split(/[\r\n]+/).map(function(e){return e.trim()}).filter(function(e){return e!=""}).splice(1);var make_stream=[];var name=null,opts={};for(var i=0;i<content.length;i++){var line=content[i];if(/^#/.test(line)){line=line.substr(1);if(/^EXTINF:/.test(line)){var list=line.substr(7).replace(/^[-0-9 ]/,"").match(/(\S+="([^\\"]|\\")*")|(\s*,\s*.*$)/g);var name=list.pop().replace(/^\s*,\s*/,"");list.forEach(function(o){o=o.match(/(^[^=]+)|(\".*\"$)/g);var key=o[0].toLowerCase();var val=o[1];var val=val.substr(1,val.length-2).replace(/\\\"/g,'"');opts[key]=val})}}else if(!!name){var config={name:name,input:[line]};if(opts["tvg-id"])config["xmltv_id"]=opts["tvg-id"];make_stream.push(config);name=null;opts={}}}return{make_stream:make_stream}};var importStart=function(hostId,content){var data,appHost=app.hosts[hostId],config=appHost.config;if(/^\s*{/.test(content)){data=JSON.parse(content)}else if(/^\s*#EXTM3U\s+/.test(content)){data=importM3U(content)}if(!data){$.err({text:"Wrong source format. Allowed only: Astra JSON, M3U"});return}var dvb_tune_map={};var softcam_map={};if(data.dvb_tune){if(!config.dvb_tune)config.dvb_tune=[];data.dvb_tune.forEach(function(item){if(!item.id){item.id=appHost.makeUid("dvb_tune")}else if(appHost.config.dvb_tune.indexOfID(item.id)!=-1){var o=item.id;item.id=appHost.makeUid("dvb_tune");dvb_tune_map[o]=item.id}if(item.enable=="false")item.enable==false;if(item.enable!=false)item.enable=true;if(item.tp){var x=item.tp.split(":");if(x.length==3){item.frequency=x[0];item.polarization=x[1].toUpperCase();item.symbolrate=x[2];delete item.tp}}if(item.lnb){var x=item.lnb.split(":");if(x.length==3){item.lof1=x[0];item.lof2=x[1];item.slof=x[2];delete item.lnb}}});config.dvb_tune=config.dvb_tune.concat(data.dvb_tune)}if(data.softcam){if(!config.softcam)config.softcam=[];data.softcam.forEach(function(item){if(!item.id){item.id=appHost.makeUid("softcam")}else if(appHost.config.softcam.indexOfID(item.id)!=-1){var o=item.id;item.id=appHost.makeUid("softcam");softcam_map[o]=item.id}if(item.enable=="false")item.enable==false;if(item.enable!=false)item.enable=true;if(!item.type)item.type="newcamd";if(item.key=="0102030405060708091011121314")delete item.key});config.softcam=config.softcam.concat(data.softcam)}if(data.make_stream){if(!config.make_stream)config.make_stream=[];data.make_stream.forEach(function(item){if(!item.id||appHost.config.make_stream.indexOfID(item.id)!=-1){item.id=appHost.makeUid("make_stream")}if(item.enable=="false")item.enable==false;if(item.enable!=false)item.enable=true;if(!item.type)item.type="spts";if(item.input){item.input.forEach(function(o,i){o=parseUrl(o);if(o){if(o.format=="dvb"&&!!o.addr&&dvb_tune_map.hasOwnProperty(o.addr)){o.addr=dvb_tune_map[o.addr]}if(o.hasOwnProperty("cam")&&o.cam!=true&&softcam_map.hasOwnProperty(o.cam)){o.cam=softcam_map[o.cam]}item.input[i]=makeUrl(o)}})}});config.make_stream=config.make_stream.concat(data.make_stream)}MainModule.removeHost(hostId);MainModule.addHost(hostId);var x=$.msg({title:appHost.name,text:'Press "Apply & Restart" button to complete import or Reload page to discard changes',delay:-1});x.addChild($.element().addClass("row").addChild($.element.button("Apply & Restart").addClass("col-4").on("click",function(event){event.target.setDisabled(true);appHost.upload(function(success){if(success)x.remove();else event.target.setDisabled(false)})})))};SettingsImportModule.render=function(hostId){var self=this,object=app.renderInit(),appHost=app.hosts[hostId];var wrap=$.element("div").addClass("settings-edit");object.addChild(wrap);var text=$.element("textarea").addClass("input monospace").addAttr("placeholder","Supported formats: Astra JSON, M3U").addAttr("tabindex","0").on("keydown",function(event){switch(event.keyCode){case 9:event.preventDefault();document.execCommand("insertText",false,"    ");break}});var btnImport=$.element.button("Import").addClass("submit").on("click",function(){importStart(hostId,text.value)});var submit=$.element("div").addClass("form-submit").addChild(btnImport);wrap.addChild(text,submit);self.on("ready",function(){text.focus()})};SettingsImportModule.init=function(){var hostId=location.hash.slice(SettingsImportModule.link.length+1);if(!app.hosts[hostId]){$.route(SettingsModule.link)}else{$.body.bindScope(SettingsImportModule.render,{},hostId)}};app.modules.push(SettingsImportModule);app.settings.push(SettingsImportModule)})();

/* settings-edit.js */

(function(){"use strict";var SettingsEditModule={label:"Edit Config",link:"#/settings-edit",order:91};SettingsEditModule.click=function(){app.selectHost(SettingsEditModule.link)};SettingsEditModule.render=function(hostId){var self=this,object=app.renderInit(),appHost=app.hosts[hostId];var wrap=$.element("div").addClass("settings-edit");object.addChild(wrap);var text=$.element("textarea").addClass("input monospace").addAttr("tabindex","0").on("keydown",function(event){switch(event.keyCode){case 9:event.preventDefault();document.execCommand("insertText",false,"    ");break}});var btnSave=$.element.button("Save").addClass("danger").on("click",function(){var r;try{r=JSON.parse(text.value||"{}")}catch(e){$.err({title:"Error",text:e.toString()});return}appHost.request({cmd:"upload",config:r},function(){try{appHost.config=r}catch(e){$.err({title:"Error",text:e.toString()});return}MainModule.removeHost(hostId);MainModule.addHost(hostId);var x=$.msg({title:appHost.name,text:'Press "Apply & Restart" button to complete export or Reload page to discard changes',delay:-1});x.addChild($.element().addClass("row").addChild($.element.button("Apply & Restart").addClass("col-4").on("click",function(event){event.target.setDisabled(true);appHost.upload(function(success){if(success)x.remove();else event.target.setDisabled(false)})})))},function(){$.err({title:"Failed to save settings"})})});var submit=$.element("div").addClass("form-submit").addChild(btnSave);wrap.addChild(text,submit);self.on("ready",function(){text.textContent=JSON.stringify($.clone(appHost.config),null,4);text.setSelectionRange(0,0);text.focus()})};SettingsEditModule.init=function(){var hostId=location.hash.slice(SettingsEditModule.link.length+1);if(!app.hosts[hostId]){$.route(SettingsModule.link)}else{$.body.bindScope(SettingsEditModule.render,{},hostId)}};app.modules.push(SettingsEditModule);app.settings.push(SettingsEditModule)})();

/* settings-license.js */

(function() {
"use strict";

var SettingsLicenseModule = {
	label: "License",
	order: 98,
};

SettingsLicenseModule.run = function() {
	var appHost = app.hosts[location.host],
		license = appHost.sysinfo.license;

	if(!license) return;

	if(license.type == 4) return;

	if(license.type == 99) {
		$.err({
			title: "License Terminated",
			delay: -1,
		}).button("Buy Now!", function() {
			this.remove();
			window.open("https://cesbo.com/astra-license", "_blank").focus();
		});
		return;
	}

	var r = Math.floor((license.expire * 1e3 - Date.now()) / (24 * 60 * 60 * 1e3));
	var d = r > 1 ? "days" : "day";
	if(license.id == "000000") {
		$.msg({
			title: "License Notification",
			text: "Unregistered evalution version! Expires in " + r + " " + d + ".",
			delay: 7,
		}).button("Buy Now!", function() {
			this.remove();
			window.open("https://cesbo.com/astra-license", "_blank").focus();
		});
		return;
	}

	if(r > 5) return;
	var x;

	if(r > 0) {
		x = $.msg({
			title: "License Notification",
			text: "Subscription expires in " + r + " " + d + "!",
			delay: 7,
		});
	} else if(license.type == 3) {
		return;
	} else {
		x = $.err({
			title: "License expired!",
			delay: 10,
		});
	}

	x.button("Renew License", function() {
		this.remove();
		window.open("https://cesbo.com/astra-renew?sn=" + license.id, "_blank").focus();
	});
};

SettingsLicenseModule.render = function(appHost) {
	var modal = this,
		license = appHost.sysinfo.license,
		form = new Form(modal.scope, modal);
	var license_type;
	var expire_title = "Expiration Date";
	modal.scope.set("$version", "Astra " + appHost.sysinfo.version + " [" + appHost.sysinfo.commit + "]");
	form.input("Version", "$version").setReadonly(true);

	switch(license.type) {
		case 1:
			license_type = license.id == "000000" ? "Unregistered evalution version!" : "Trial";
			break;
		case 2:
			license_type = "Subscription";
			break;
		case 3:
			license_type = "Corporate";
			break;
		case 4:
			expire_title = "Purchase Date";
			license_type = "Lifetime";
			break;
		case 99:
			expire_title = null;
			license_type = "Terminated";
			break;
	}

	if(license.id != "000000") {
		modal.scope.set("$sn", license.id);
		form.input("SN", "$sn").setReadonly(true);
	}

	modal.scope.set("$type", license_type);
	form.input("Type", "$type").setReadonly(true);
	if(license.email != "DEMO") {
		var to = license.email;
		if(license.company) to += " (" + license.company + ")";
		modal.scope.set("$to", to);
		form.input("Licensed To", "$to").setReadonly(true);
	}

	if(!!expire_title) {
		modal.scope.set("$expire", time2ddmmmyyyy(license.expire));
		form.input(expire_title, "$expire").setReadonly(true);
	}

	form.hr();

	var btnOk = $.element
		.button("Ok")
		.addClass("submit")
		.on("click", function() {
			modal.remove();
		});

	var btnPurchase;
	if(license.type == 1 || license.type == 99) {
		btnPurchase = $.element.button("Buy Now!");
	} else if(license.type == 3 && license.expire * 1e3 > Date.now()) {
	} else if(license.type == 4) {
	} else {
		btnPurchase = $.element.button("Renew");
	}

	if(btnPurchase) {
		btnPurchase.on("click", function() {
			if(license.type == 99 || license.id == "000000") window.open("https://cesbo.com/astra-license", "_blank").focus();
			else window.open("https://cesbo.com/astra-renew?sn=" + license.id, "_blank").focus();
		});
	}

	form.submit().addChild(btnOk, btnPurchase);
};

SettingsLicenseModule.click = function() {
	$.modal().bindScope(SettingsLicenseModule.render, {}, app.hosts[location.host]);
};

app.modules.push(SettingsLicenseModule);
app.settings.push(SettingsLicenseModule);
})();

/* settings-restart.js */

(function(){"use strict";var SettingsRestartModule={label:"Restart",order:99};SettingsRestartModule.click=function(){var modal=$.modal();modal.addClass("main-menu");$.forEach(app.hosts,function(appHost,hostId){var x=$.element("a").setText(appHost.name).addAttr("href","#");x.on("click",function(event){event.preventDefault();modal.remove();appHost.restart()});modal.addChild(x)});modal.addChild($.element("hr"));modal.addChild($.element("a").setText("Cancel").addClass("text-center").addAttr("href","#/").on("click",function(event){event.preventDefault();modal.remove()}))};app.modules.push(SettingsRestartModule);app.settings.push(SettingsRestartModule)})();

/* log.js */

(function() {
"use strict";

window.LogModule = {
	label: "Log",
	link: "#/log",
	order: 9,
	search: true,
	menu: [
		{
			label: "Settings",
			hide: app.observer == true,
			click: function() {
				LogModule.openSettings();
			},
		},
		{
			label: "Clear",
			hide: app.observer == true,
			click: function() {
				LogModule.inner.empty();
				LogModule.log = [];
				LogModule.logSkip = 0;
			},
		},
	],
};

LogModule.renderSettings = function() {
	var modal = this,
		form = new Form(modal.scope, modal);

	form.checkbox("API Access", "api_access");
	form.checkbox("Debug", "debug");
	form.hr();

	var btnApply = $.element
		.button("Apply")
		.addClass("submit")
		.on("click", function() {
			if(modal.scope.validate()) modal.submit();
		});

	var btnCancel = $.element
		.button("Cancel")
		.on("click", function() {
			modal.remove();
		});

	form.submit().addChild(btnApply, btnCancel);
};

LogModule.openSettings = function() {
	var appHost = app.hosts[location.host],
		modalData = $.clone(appHost.config.log) || {};

	$.modal()
		.bindScope(LogModule.renderSettings, modalData)
		.on("submit", function() {
			var data = this.scope.serialize();
			appHost.request({
				cmd: "set-log",
				set: data,
			}, function() {
			}, function() {
				$.err({ title: "Failed to save log settings" });
			});
		});
};

LogModule.run = function() {
	LogModule.inner = $.element("div").addClass("log monospace");
	LogModule.log = [];
	LogModule.logSkip = 0;
	LogModule.isReady = false;

	var appHost = app.hosts[location.host];

	appHost.request({ cmd: "log" }, function(response) {
		var data = response.data;
		if(data.log) {
			var logData = [];
			Array.prototype.push.apply(logData, data.log);
			Array.prototype.push.apply(logData, LogModule.log);
			if(logData.length > 2e3) logData.splice(0, logData.length - 2e3);
			LogModule.log = logData;
			LogModule.logSkip = 0;
		}
		LogModule.isReady = true;
	});

	app.on("log_event", function(event) {
		if(event.data.log) {
			Array.prototype.push.apply(LogModule.log, event.data.log);
			if(LogModule.log.length > 2e3) {
				var drop = LogModule.log.length - 2e3;
				LogModule.log.splice(0, drop);
				LogModule.logSkip = Math.max(0, LogModule.logSkip - drop);
			}
		}

		if(event.data.set) {
			appHost.config.log = event.data.set;
		}
	});
};

LogModule.render = function() {
	var self = this,
		object = app.renderInit();

	object.addChild(LogModule.inner);

	var search = "";
	var autoScroll = true;

	var logGrep = function(tail) {
		var il = LogModule.inner.childNodes,
			l = il.length,
			i = !tail ? 0 : l - tail;

		for(; i < l; ++i) {
			var e = il[i].removeClass("hide");
			if(search && e.lastChild.textContent.toLowerCase().indexOf(search) == -1) e.addClass("hide");
		}

		if(autoScroll) {
			window.scrollTo(0, $.base.scrollHeight);
		}
	};

	var logLimit = 2e3;
	var stepLimit = 100;

	var dateFormat = function(d) {
		d = new Date(d);
		var dd = ("0" + d.getDate()).slice(-2);
		var dm = monthMap[d.getMonth()];
		var th = ("0" + d.getHours()).slice(-2);
		var tm = ("0" + d.getMinutes()).slice(-2);
		var ts = ("0" + d.getSeconds()).slice(-2);
		return dm + " " + dd + " " + th + ":" + tm + ":" + ts;
	};

	var makeItem = function(e) {
		var li = $.element("div").addClass("log-item log-" + e.type);
		var ld = $.element("div")
			.addClass("log-time")
			.setText(dateFormat(e.time * 1e3));
		var lt = $.element("div").addClass("log-text").setText(e.text);
		li.addChild(ld).addChild(lt);
		LogModule.inner.addChild(li);
		if(LogModule.inner.childNodes.length > logLimit) LogModule.inner.firstChild.remove();
	};

	var cacheTimeout = null;
	var cacheUpdate = function() {
		if(!LogModule.isReady) {
			cacheTimeout = setTimeout(cacheUpdate, 200);
			return;
		}
		if(LogModule.logSkip == LogModule.log.length) {
			cacheTimeout = setTimeout(cacheUpdate, 1e3);
			return;
		}
		var ds = Math.min(LogModule.log.length - LogModule.logSkip, stepLimit);
		var dc = LogModule.logSkip + ds;
		for(var i = LogModule.logSkip; i < dc; ++i) makeItem(LogModule.log[i]);
		LogModule.logSkip += ds;
		logGrep(ds);
		cacheTimeout = setTimeout(cacheUpdate, 50);
	};

	cacheUpdate();
	logGrep();

	app.search = function(value) {
		search = value || "";
		search = search.toLowerCase();
		if(!search) autoScroll = true;
		logGrep();
	};

	var autoScrollCheck = function() {
		autoScroll = window.innerHeight + window.scrollY + 40 >= object.offsetHeight;
	};

	window.addEventListener("scroll", autoScrollCheck);

	self.on("destroy", function() {
		window.removeEventListener("scroll", autoScrollCheck);
		clearTimeout(cacheTimeout);
	});

	self.on("ready", function() {
		document.querySelector(".search").focus();
	});
};

LogModule.init = function() {
	$.body.bindScope(LogModule.render, {});
};

app.modules.push(LogModule);
app.menu.push(LogModule);
})();

/* analyze-ui.js */

var analyzeUi=function(){"use strict";var t=function(t,e,a,r,s,n,i,o,d,c){"boolean"!=typeof i&&(d=o,o=i,i=!1);var l,p="function"==typeof a?a.options:a;if(t&&t.render&&(p.render=t.render,p.staticRenderFns=t.staticRenderFns,p._compiled=!0,s&&(p.functional=!0)),r&&(p._scopeId=r),n?(l=function(t){(t=t||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext)||"undefined"==typeof __VUE_SSR_CONTEXT__||(t=__VUE_SSR_CONTEXT__),e&&e.call(this,d(t)),t&&t._registeredComponents&&t._registeredComponents.add(n)},p._ssrRegister=l):e&&(l=i?function(){e.call(this,c(this.$root.$options.shadowRoot))}:function(t){e.call(this,o(t))}),l)if(p.functional){var u=p.render;p.render=function(t,e){return l.call(e),u(t,e)}}else{var _=p.beforeCreate;p.beforeCreate=_?[].concat(_,l):[l]}return a};var e=t({render:function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("div",[a("span",{staticClass:"ok"},[t._v(t._s(t.data.bitrate)+"Kbit/s")]),a("span",{class:[t.data.cc_errors?"er":"ok"],staticStyle:{"padding-left":".5rem"}},[t._v("CC:"+t._s(t.data.cc_errors))]),a("span",{class:[t.data.pes_errors?"er":"ok"],staticStyle:{"padding-left":".5rem"}},[t._v("PES:"+t._s(t.data.pes_errors))]),t.data.scrambled?a("span",{staticStyle:{"padding-left":".5rem"}},[t._v("🔒")]):t._e()])},staticRenderFns:[]},void 0,{props:{data:{type:Object,default:()=>({bitrate:0,cc_errors:0,pes_errors:0,scrambled:!1})}}},void 0,!1,void 0,void 0,void 0);var a=t({render:function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("div",[a("span",[a("strong",[t._v("PAT TSID:"+t._s(t.data.tsid))])]),a("ul",{staticClass:"psi"},t._l(t.data.programs,function(e){return a("li",{key:e.pnr},[t._v("PNR:"+t._s(e.pnr)+" PID:"+t._s(e.pid))])}),0)])},staticRenderFns:[]},void 0,{props:{data:{type:Object}}},void 0,!1,void 0,void 0,void 0);const r=t=>"0x"+("0000"+t.toString(16)).slice(-4);var s=t({render:function(){var t=this.$createElement;return(this._self._c||t)("div",{domProps:{innerHTML:this._s(this.descInfo)}})},staticRenderFns:[]},void 0,{props:{data:{type:Object}},computed:{descInfo(){return(t=>{let e="";switch(t.type_id){case 9:return`CAS CaID:${r(t.caid)} PID:${t.pid}`;case 10:return`Language: ${t.lang}`;case 64:return`Name: ${t.network_name}`;case 67:return`DVB-S Position: ${t.orbital_position} Modulation: ${t.modulation} Tp: ${t.frequency}:${t.polarization}:${t.symbolrate}`;case 68:return`DVB-C Modulation: ${t.modulation} Frequency: ${t.frequency} Symbolrate: ${t.symbolrate}`;case 72:return`Provider: ${t.service_provider}<br/>Service: ${t.service_name}`;case 77:return`Language: ${t.lang} Title: ${t.event_name}`;case 82:return`Stream ID: ${t.stream_id}`;case 83:return`CaID: ${r(t.caid)}`;case 84:let a=["Movie/Drama","News","Show","Sports","Children's","Music","Arts/Culture","Social/Economics","Education/Science","Hobbies"];for(let r in t.items)if(t.network_name.hasOwnProperty(r)){e+=`Content: ${a[t.items[r].cn_l1]}<br/>`}return e;case 86:return`Teletext Language: ${t.lang}`;case 89:return`Subtitling Language: ${t.lang}`;case 90:let s=t.hierarchy||"",n=t.transmission||"";return`DVB-T Modulation: ${t.modulation} Frequency: ${t.frequency} Bandwidth: ${t.bandwidth}${s} Guard: ${t.guard_interval}${n}`;case 91:for(let a in t.network_name)t.network_name.hasOwnProperty(a)&&(e+=`Name.${a}:${t.network_name[a]}<br/>`);return e;case 131:for(let a in t.lcn)t.lcn.hasOwnProperty(a)&&(e+=`Lcn: ${t.lcn[a].lcn} Pnr: ${t.lcn[a].pnr}<br/>`);return e;default:return"unknown"==t.type_name?`Descriptor: ${t.data}`:`ERR. TypeID:${t.type_id}`}})(this.data)}}},void 0,!1,void 0,void 0,void 0);var n=t({render:function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("div",[a("span",[a("strong",[t._v("PMT PNR:"+t._s(t.data.pnr))])]),a("ul",{staticClass:"psi"},[a("li",[t._v("PCR PID:"+t._s(t.data.pcr))]),t._l(t.data.descriptors,function(e,r){return a("li",{key:r},[t._o(a("psi-desc",{attrs:{data:e}}),0,r)],1)})],2),t._l(t.data.streams,function(e){return a("ul",{key:e.pid,staticClass:"psi"},[a("li",[t._v(t._s(e.type_name)+" PID:"+t._s(e.pid)+" TYPE:"+t._s(t.typeToString(e.type_id)))]),t._l(e.descriptors,function(e,r){return a("li",{key:r},[t._o(a("psi-desc",{attrs:{data:e}}),1,r)],1)})],2)})],2)},staticRenderFns:[]},void 0,{components:{PsiDesc:s},props:{data:{type:Object}},methods:{typeToString:function(t){let e="0x"+("00"+t.toString(16).toUpperCase()).slice(-2)+" ";switch(t){case 1:e+="ISO/IEC 11172 Video";break;case 2:e+="ISO/IEC 13818-2 Video";break;case 16:e+="ISO/IEC 14496-2 Visual";break;case 27:e+="ISO/IEC 14496-10 Video | H.264";break;case 36:e+="ISO/IEC 23008-2 Video | H.265";break;case 3:e+="ISO/IEC 11172 Audio";break;case 4:e+="ISO/IEC 13818-3 Audio";break;case 15:e+="ISO/IEC 13818-7 Audio (ADTS)";break;case 17:e+="ISO/IEC 14496-3 Audio (LATM)";break;case 6:e+="ISO/IEC 13818-1 PES private data";break;default:e+="Unknown Stream Type"}return e}}},void 0,!1,void 0,void 0,void 0);var i=t({render:function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("div",[a("span",[a("strong",[t._v("SDT TSID:"+t._s(t.data.tsid))])]),t._l(t.data.services,function(e){return a("ul",{key:e.sid,staticClass:"psi"},[a("li",[t._v("PNR:"+t._s(e.sid))]),t._l(e.descriptors,function(e,r){return a("li",{key:r},[t._o(a("psi-desc",{attrs:{data:e}}),0,r)],1)})],2)})],2)},staticRenderFns:[]},void 0,{components:{PsiDesc:s},props:{data:{type:Object}}},void 0,!1,void 0,void 0,void 0);var o=t({render:function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("div",[a("span",[a("strong",[t._v("NIT ID:"+t._s(t.data.network_id))])]),t.data.descriptors?a("ul",{staticClass:"psi"},t._l(t.data.descriptors,function(e,r){return a("li",{key:r},[t._o(a("psi-desc",{attrs:{data:e}}),0,r)],1)}),0):t._e(),t._l(t.data.streams,function(e){return a("ul",{key:e.tsid,staticClass:"psi"},[a("li",[t._v("NIT TSID:"+t._s(e.tsid)+" ONID:"+t._s(e.onid))]),t._l(t.data.descriptors,function(e,r){return a("li",{key:r},[t._o(a("psi-desc",{attrs:{data:e}}),1,r)],1)})],2)})],2)},staticRenderFns:[]},void 0,{components:{PsiDesc:s},props:{data:{type:Object}}},void 0,!1,void 0,void 0,void 0);var d=t({render:function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("div",[a("analyze-stat",{attrs:{data:t.analyzeData}}),a("hr"),t.patData?a("psi-pat",{attrs:{data:t.patData}}):t._e(),t._l(t.pmtList,function(t){return a("psi-pmt",{key:t.pnr,attrs:{data:t}})}),t.sdtData?a("psi-sdt",{attrs:{data:t.sdtData}}):t._e(),t.nitData?a("psi-nit",{attrs:{data:t.nitData}}):t._e()],2)},staticRenderFns:[]},void 0,{components:{AnalyzeStat:e,PsiPat:a,PsiPmt:n,PsiSdt:i,PsiNit:o},data:()=>({analyzeData:void 0,patData:void 0,pmtList:[],sdtData:void 0,nitData:void 0}),methods:{setData(t){if(t.psi)switch(t.psi){case"pat":this.patData=t,this.pmtList=[];break;case"pmt":this.pmtList.push(t);break;case"sdt":this.sdtData=t;break;case"nit":this.nitData=t}else t.analyze&&(this.analyzeData=t.total)}}},void 0,!1,void 0,void 0,void 0);let c;return{render:t=>{c=new Vue({...d}).$mount(t)},process:t=>{c.setData(t)},destroy:()=>{for(c.$destroy();c.$el.firstChild;)c.$el.removeChild(c.$el.firstChild);c=void 0},copy:()=>{let t=document.createElement("textarea");t.setAttribute("style","width: 1px; border: 0; opacity: 0;"),document.body.appendChild(t),t.value=c.$el.innerText,t.select(),document.execCommand("copy"),document.body.removeChild(t)}}}();

</script><div></div>
<script src="/mod.js"></script>


</body></html>

                             

Screenshot: