사용자:Senouis/자바스크립트: 두 판 사이의 차이

리버티게임, 모두가 만들어가는 자유로운 게임
리버티게임>Senouis
편집 요약 없음
리버티게임>Senouis
편집 요약 없음
 
(같은 사용자의 중간 판 4개는 보이지 않습니다)
1번째 줄: 1번째 줄:
{{#css:
{{PluginX|script=사용자:Senouis/자바스크립트/plugin1.js|creator=Senouis|name=백괴포트리스 1.0}}
/*!
* Bootstrap v3.3.4 (http://getbootstrap.com)
* Copyright 2011-2015 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
*//*! normalize.css v3.0.2 | MIT License | git.io/normalize */
html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{margin:.67em 0;font-size:2em}mark{color:#000;background:#ff0}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{height:0;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{margin:0;font:inherit;color:inherit}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}input{line-height:normal}input[type=checkbox],input[type=radio]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{padding:.35em .625em .75em;margin:0 2px;border:1px solid silver}legend{padding:0;border:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-spacing:0;border-collapse:collapse}td,th{padding:0}/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */@media print{*,:after,:before{color:#000!important;text-shadow:none!important;background:0 0!important;-webkit-box-shadow:none!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="javascript:"]:after,a[href^="#"]:after{content:""}blockquote,pre{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}select{background:#fff!important}.navbar{display:none}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #ddd!important}}@font-face{font-family:'Glyphicons Halflings';src:url(../fonts/glyphicons-halflings-regular.eot);src:url(../fonts/glyphicons-halflings-regular.eot?#iefix) format('embedded-opentype'),url(../fonts/glyphicons-halflings-regular.woff2) format('woff2'),url(../fonts/glyphicons-halflings-regular.woff) format('woff'),url(../fonts/glyphicons-halflings-regular.ttf) format('truetype'),url(../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular) format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\2a"}.glyphicon-plus:before{content:"\2b"}.glyphicon-eur:before,.glyphicon-euro:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.glyphicon-cd:before{content:"\e201"}.glyphicon-save-file:before{content:"\e202"}.glyphicon-open-file:before{content:"\e203"}.glyphicon-level-up:before{content:"\e204"}.glyphicon-copy:before{content:"\e205"}.glyphicon-paste:before{content:"\e206"}.glyphicon-alert:before{content:"\e209"}.glyphicon-equalizer:before{content:"\e210"}.glyphicon-king:before{content:"\e211"}.glyphicon-queen:before{content:"\e212"}.glyphicon-pawn:before{content:"\e213"}.glyphicon-bishop:before{content:"\e214"}.glyphicon-knight:before{content:"\e215"}.glyphicon-baby-formula:before{content:"\e216"}.glyphicon-tent:before{content:"\26fa"}.glyphicon-blackboard:before{content:"\e218"}.glyphicon-bed:before{content:"\e219"}.glyphicon-apple:before{content:"\f8ff"}.glyphicon-erase:before{content:"\e221"}.glyphicon-hourglass:before{content:"\231b"}.glyphicon-lamp:before{content:"\e223"}.glyphicon-duplicate:before{content:"\e224"}.glyphicon-piggy-bank:before{content:"\e225"}.glyphicon-scissors:before{content:"\e226"}.glyphicon-bitcoin:before{content:"\e227"}.glyphicon-btc:before{content:"\e227"}.glyphicon-xbt:before{content:"\e227"}.glyphicon-yen:before{content:"\00a5"}.glyphicon-jpy:before{content:"\00a5"}.glyphicon-ruble:before{content:"\20bd"}.glyphicon-rub:before{content:"\20bd"}.glyphicon-scale:before{content:"\e230"}.glyphicon-ice-lolly:before{content:"\e231"}.glyphicon-ice-lolly-tasted:before{content:"\e232"}.glyphicon-education:before{content:"\e233"}.glyphicon-option-horizontal:before{content:"\e234"}.glyphicon-option-vertical:before{content:"\e235"}.glyphicon-menu-hamburger:before{content:"\e236"}.glyphicon-modal-window:before{content:"\e237"}.glyphicon-oil:before{content:"\e238"}.glyphicon-grain:before{content:"\e239"}.glyphicon-sunglasses:before{content:"\e240"}.glyphicon-text-size:before{content:"\e241"}.glyphicon-text-color:before{content:"\e242"}.glyphicon-text-background:before{content:"\e243"}.glyphicon-object-align-top:before{content:"\e244"}.glyphicon-object-align-bottom:before{content:"\e245"}.glyphicon-object-align-horizontal:before{content:"\e246"}.glyphicon-object-align-left:before{content:"\e247"}.glyphicon-object-align-vertical:before{content:"\e248"}.glyphicon-object-align-right:before{content:"\e249"}.glyphicon-triangle-right:before{content:"\e250"}.glyphicon-triangle-left:before{content:"\e251"}.glyphicon-triangle-bottom:before{content:"\e252"}.glyphicon-triangle-top:before{content:"\e253"}.glyphicon-console:before{content:"\e254"}.glyphicon-superscript:before{content:"\e255"}.glyphicon-subscript:before{content:"\e256"}.glyphicon-menu-left:before{content:"\e257"}.glyphicon-menu-right:before{content:"\e258"}.glyphicon-menu-down:before{content:"\e259"}.glyphicon-menu-up:before{content:"\e260"}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}:after,:before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#333;background-color:#fff}button,input,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#337ab7;text-decoration:none}a:focus,a:hover{color:#23527c;text-decoration:underline}a:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.carousel-inner>.item>a>img,.carousel-inner>.item>img,.img-responsive,.thumbnail a>img,.thumbnail>img{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{display:inline-block;max-width:100%;height:auto;padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}[role=button]{cursor:pointer}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-weight:400;line-height:1;color:#777}.h1,.h2,.h3,h1,h2,h3{margin-top:20px;margin-bottom:10px}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small{font-size:65%}.h4,.h5,.h6,h4,h5,h6{margin-top:10px;margin-bottom:10px}.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-size:75%}.h1,h1{font-size:36px}.h2,h2{font-size:30px}.h3,h3{font-size:24px}.h4,h4{font-size:18px}.h5,h5{font-size:14px}.h6,h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:300;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}.small,small{font-size:85%}.mark,mark{padding:.2em;background-color:#fcf8e3}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#777}.text-primary{color:#337ab7}a.text-primary:hover{color:#286090}.text-success{color:#3c763d}a.text-success:hover{color:#2b542c}.text-info{color:#31708f}a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:hover{color:#843534}.bg-primary{color:#fff;background-color:#337ab7}a.bg-primary:hover{background-color:#286090}.bg-success{background-color:#dff0d8}a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:hover{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ol,ul{margin-top:0;margin-bottom:10px}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;margin-left:-5px;list-style:none}.list-inline>li{display:inline-block;padding-right:5px;padding-left:5px}dl{margin-top:0;margin-bottom:20px}dd,dt{line-height:1.42857143}dt{font-weight:700}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[data-original-title],abbr[title]{cursor:help;border-bottom:1px dotted #777}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote ol:last-child,blockquote p:last-child,blockquote ul:last-child{margin-bottom:0}blockquote .small,blockquote footer,blockquote small{display:block;font-size:80%;line-height:1.42857143;color:#777}blockquote .small:before,blockquote footer:before,blockquote small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;text-align:right;border-right:5px solid #eee;border-left:0}.blockquote-reverse .small:before,.blockquote-reverse footer:before,.blockquote-reverse small:before,blockquote.pull-right .small:before,blockquote.pull-right footer:before,blockquote.pull-right small:before{content:''}.blockquote-reverse .small:after,.blockquote-reverse footer:after,.blockquote-reverse small:after,blockquote.pull-right .small:after,blockquote.pull-right footer:after,blockquote.pull-right small:after{content:'\00A0 \2014'}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.25);box-shadow:inset 0 -1px 0 rgba(0,0,0,.25)}kbd kbd{padding:0;font-size:100%;font-weight:700;-webkit-box-shadow:none;box-shadow:none}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;color:#333;word-break:break-all;word-wrap:break-word;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.row{margin-right:-15px;margin-left:-15px}.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{position:relative;min-height:1px;padding-right:15px;padding-left:15px}.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0}}table{background-color:transparent}caption{padding-top:8px;padding-bottom:8px;color:#777;text-align:left}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:20px}.table>tbody>tr>td,.table>tbody>tr>th,.table>tfoot>tr>td,.table>tfoot>tr>th,.table>thead>tr>td,.table>thead>tr>th{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>td,.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>td,.table>thead:first-child>tr:first-child>th{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>tbody>tr>td,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>td,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>thead>tr>th{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>tbody>tr>td,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>td,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border:1px solid #ddd}.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border-bottom-width:2px}.table-striped>tbody>tr:nth-of-type(odd){background-color:#f9f9f9}.table-hover>tbody>tr:hover{background-color:#f5f5f5}table col[class*=col-]{position:static;display:table-column;float:none}table td[class*=col-],table th[class*=col-]{position:static;display:table-cell;float:none}.table>tbody>tr.active>td,.table>tbody>tr.active>th,.table>tbody>tr>td.active,.table>tbody>tr>th.active,.table>tfoot>tr.active>td,.table>tfoot>tr.active>th,.table>tfoot>tr>td.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>thead>tr.active>th,.table>thead>tr>td.active,.table>thead>tr>th.active{background-color:#f5f5f5}.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr.active:hover>th,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover{background-color:#e8e8e8}.table>tbody>tr.success>td,.table>tbody>tr.success>th,.table>tbody>tr>td.success,.table>tbody>tr>th.success,.table>tfoot>tr.success>td,.table>tfoot>tr.success>th,.table>tfoot>tr>td.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>thead>tr.success>th,.table>thead>tr>td.success,.table>thead>tr>th.success{background-color:#dff0d8}.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr.success:hover>th,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover{background-color:#d0e9c6}.table>tbody>tr.info>td,.table>tbody>tr.info>th,.table>tbody>tr>td.info,.table>tbody>tr>th.info,.table>tfoot>tr.info>td,.table>tfoot>tr.info>th,.table>tfoot>tr>td.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>thead>tr.info>th,.table>thead>tr>td.info,.table>thead>tr>th.info{background-color:#d9edf7}.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr.info:hover>th,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover{background-color:#c4e3f3}.table>tbody>tr.warning>td,.table>tbody>tr.warning>th,.table>tbody>tr>td.warning,.table>tbody>tr>th.warning,.table>tfoot>tr.warning>td,.table>tfoot>tr.warning>th,.table>tfoot>tr>td.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>thead>tr.warning>th,.table>thead>tr>td.warning,.table>thead>tr>th.warning{background-color:#fcf8e3}.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr.warning:hover>th,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover{background-color:#faf2cc}.table>tbody>tr.danger>td,.table>tbody>tr.danger>th,.table>tbody>tr>td.danger,.table>tbody>tr>th.danger,.table>tfoot>tr.danger>td,.table>tfoot>tr.danger>th,.table>tfoot>tr>td.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>thead>tr.danger>th,.table>thead>tr>td.danger,.table>thead>tr>th.danger{background-color:#f2dede}.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr.danger:hover>th,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover{background-color:#ebcccc}.table-responsive{min-height:.01%;overflow-x:auto}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>td,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>thead>tr>th{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:700}input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=checkbox],input[type=radio]{margin:4px 0 0;margin-top:1px \9;line-height:normal}input[type=file]{display:block}input[type=range]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type=file]:focus,input[type=checkbox]:focus,input[type=radio]:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.42857143;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{background-color:#eee;opacity:1}.form-control[disabled],fieldset[disabled] .form-control{cursor:not-allowed}textarea.form-control{height:auto}input[type=search]{-webkit-appearance:none}@media screen and (-webkit-min-device-pixel-ratio:0){input[type=date],input[type=time],input[type=datetime-local],input[type=month]{line-height:34px}.input-group-sm input[type=date],.input-group-sm input[type=time],.input-group-sm input[type=datetime-local],.input-group-sm input[type=month],input[type=date].input-sm,input[type=time].input-sm,input[type=datetime-local].input-sm,input[type=month].input-sm{line-height:30px}.input-group-lg input[type=date],.input-group-lg input[type=time],.input-group-lg input[type=datetime-local],.input-group-lg input[type=month],input[type=date].input-lg,input[type=time].input-lg,input[type=datetime-local].input-lg,input[type=month].input-lg{line-height:46px}}.form-group{margin-bottom:15px}.checkbox,.radio{position:relative;display:block;margin-top:10px;margin-bottom:10px}.checkbox label,.radio label{min-height:20px;padding-left:20px;margin-bottom:0;font-weight:400;cursor:pointer}.checkbox input[type=checkbox],.checkbox-inline input[type=checkbox],.radio input[type=radio],.radio-inline input[type=radio]{position:absolute;margin-top:4px \9;margin-left:-20px}.checkbox+.checkbox,.radio+.radio{margin-top:-5px}.checkbox-inline,.radio-inline{position:relative;display:inline-block;padding-left:20px;margin-bottom:0;font-weight:400;vertical-align:middle;cursor:pointer}.checkbox-inline+.checkbox-inline,.radio-inline+.radio-inline{margin-top:0;margin-left:10px}fieldset[disabled] input[type=checkbox],fieldset[disabled] input[type=radio],input[type=checkbox].disabled,input[type=checkbox][disabled],input[type=radio].disabled,input[type=radio][disabled]{cursor:not-allowed}.checkbox-inline.disabled,.radio-inline.disabled,fieldset[disabled] .checkbox-inline,fieldset[disabled] .radio-inline{cursor:not-allowed}.checkbox.disabled label,.radio.disabled label,fieldset[disabled] .checkbox label,fieldset[disabled] .radio label{cursor:not-allowed}.form-control-static{min-height:34px;padding-top:7px;padding-bottom:7px;margin-bottom:0}.form-control-static.input-lg,.form-control-static.input-sm{padding-right:0;padding-left:0}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}select[multiple].input-sm,textarea.input-sm{height:auto}.form-group-sm .form-control{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.form-group-sm .form-control{height:30px;line-height:30px}select[multiple].form-group-sm .form-control,textarea.form-group-sm .form-control{height:auto}.form-group-sm .form-control-static{height:30px;min-height:32px;padding:5px 10px;font-size:12px;line-height:1.5}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-lg{height:46px;line-height:46px}select[multiple].input-lg,textarea.input-lg{height:auto}.form-group-lg .form-control{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.form-group-lg .form-control{height:46px;line-height:46px}select[multiple].form-group-lg .form-control,textarea.form-group-lg .form-control{height:auto}.form-group-lg .form-control-static{height:46px;min-height:38px;padding:10px 16px;font-size:18px;line-height:1.3333333}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:34px;height:34px;line-height:34px;text-align:center;pointer-events:none}.input-lg+.form-control-feedback{width:46px;height:46px;line-height:46px}.input-sm+.form-control-feedback{width:30px;height:30px;line-height:30px}.has-success .checkbox,.has-success .checkbox-inline,.has-success .control-label,.has-success .help-block,.has-success .radio,.has-success .radio-inline,.has-success.checkbox label,.has-success.checkbox-inline label,.has-success.radio label,.has-success.radio-inline label{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;background-color:#dff0d8;border-color:#3c763d}.has-success .form-control-feedback{color:#3c763d}.has-warning .checkbox,.has-warning .checkbox-inline,.has-warning .control-label,.has-warning .help-block,.has-warning .radio,.has-warning .radio-inline,.has-warning.checkbox label,.has-warning.checkbox-inline label,.has-warning.radio label,.has-warning.radio-inline label{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;background-color:#fcf8e3;border-color:#8a6d3b}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .checkbox,.has-error .checkbox-inline,.has-error .control-label,.has-error .help-block,.has-error .radio,.has-error .radio-inline,.has-error.checkbox label,.has-error.checkbox-inline label,.has-error.radio label,.has-error.radio-inline label{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;background-color:#f2dede;border-color:#a94442}.has-error .form-control-feedback{color:#a94442}.has-feedback label~.form-control-feedback{top:25px}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-static{display:inline-block}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .form-control,.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .checkbox,.form-inline .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .checkbox label,.form-inline .radio label{padding-left:0}.form-inline .checkbox input[type=checkbox],.form-inline .radio input[type=radio]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .checkbox,.form-horizontal .checkbox-inline,.form-horizontal .radio,.form-horizontal .radio-inline{padding-top:7px;margin-top:0;margin-bottom:0}.form-horizontal .checkbox,.form-horizontal .radio{min-height:27px}.form-horizontal .form-group{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.form-horizontal .control-label{padding-top:7px;margin-bottom:0;text-align:right}}.form-horizontal .has-feedback .form-control-feedback{right:15px}@media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:14.33px}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:6px}}.btn{display:inline-block;padding:6px 12px;margin-bottom:0;font-size:14px;font-weight:400;line-height:1.42857143;text-align:center;white-space:nowrap;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-image:none;border:1px solid transparent;border-radius:4px}.btn.active.focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn:active:focus,.btn:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn.focus,.btn:focus,.btn:hover{color:#333;text-decoration:none}.btn.active,.btn:active{background-image:none;outline:0;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{pointer-events:none;cursor:not-allowed;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none;opacity:.65}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default.active,.btn-default.focus,.btn-default:active,.btn-default:focus,.btn-default:hover,.open>.dropdown-toggle.btn-default{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{background-image:none}.btn-default.disabled,.btn-default.disabled.active,.btn-default.disabled.focus,.btn-default.disabled:active,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled],.btn-default[disabled].active,.btn-default[disabled].focus,.btn-default[disabled]:active,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default,fieldset[disabled] .btn-default.active,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:active,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#337ab7;border-color:#2e6da4}.btn-primary.active,.btn-primary.focus,.btn-primary:active,.btn-primary:focus,.btn-primary:hover,.open>.dropdown-toggle.btn-primary{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled,.btn-primary.disabled.active,.btn-primary.disabled.focus,.btn-primary.disabled:active,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled],.btn-primary[disabled].active,.btn-primary[disabled].focus,.btn-primary[disabled]:active,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-primary.active,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:active,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#337ab7;border-color:#2e6da4}.btn-primary .badge{color:#337ab7;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success.active,.btn-success.focus,.btn-success:active,.btn-success:focus,.btn-success:hover,.open>.dropdown-toggle.btn-success{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{background-image:none}.btn-success.disabled,.btn-success.disabled.active,.btn-success.disabled.focus,.btn-success.disabled:active,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled],.btn-success[disabled].active,.btn-success[disabled].focus,.btn-success[disabled]:active,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success,fieldset[disabled] .btn-success.active,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:active,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info.active,.btn-info.focus,.btn-info:active,.btn-info:focus,.btn-info:hover,.open>.dropdown-toggle.btn-info{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{background-image:none}.btn-info.disabled,.btn-info.disabled.active,.btn-info.disabled.focus,.btn-info.disabled:active,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled],.btn-info[disabled].active,.btn-info[disabled].focus,.btn-info[disabled]:active,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info,fieldset[disabled] .btn-info.active,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:active,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning.active,.btn-warning.focus,.btn-warning:active,.btn-warning:focus,.btn-warning:hover,.open>.dropdown-toggle.btn-warning{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled,.btn-warning.disabled.active,.btn-warning.disabled.focus,.btn-warning.disabled:active,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled],.btn-warning[disabled].active,.btn-warning[disabled].focus,.btn-warning[disabled]:active,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning,fieldset[disabled] .btn-warning.active,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:active,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger.active,.btn-danger.focus,.btn-danger:active,.btn-danger:focus,.btn-danger:hover,.open>.dropdown-toggle.btn-danger{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled,.btn-danger.disabled.active,.btn-danger.disabled.focus,.btn-danger.disabled:active,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled],.btn-danger[disabled].active,.btn-danger[disabled].focus,.btn-danger[disabled]:active,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger,fieldset[disabled] .btn-danger.active,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:active,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{font-weight:400;color:#337ab7;border-radius:0}.btn-link,.btn-link.active,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:active,.btn-link:focus,.btn-link:hover{border-color:transparent}.btn-link:focus,.btn-link:hover{color:#23527c;text-decoration:underline;background-color:transparent}.btn-link[disabled]:focus,.btn-link[disabled]:hover,fieldset[disabled] .btn-link:focus,fieldset[disabled] .btn-link:hover{color:#777;text-decoration:none}.btn-group-lg>.btn,.btn-lg{padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.btn-group-sm>.btn,.btn-sm{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-xs>.btn,.btn-xs{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition-timing-function:ease;-o-transition-timing-function:ease;transition-timing-function:ease;-webkit-transition-duration:.35s;-o-transition-duration:.35s;transition-duration:.35s;-webkit-transition-property:height,visibility;-o-transition-property:height,visibility;transition-property:height,visibility}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px dashed;border-right:4px solid transparent;border-left:4px solid transparent}.dropdown,.dropup{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;font-size:14px;text-align:left;list-style:none;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175)}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.42857143;color:#333;white-space:nowrap}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{color:#262626;text-decoration:none;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{color:#fff;text-decoration:none;background-color:#337ab7;outline:0}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{color:#777}.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{text-decoration:none;cursor:not-allowed;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{right:0;left:auto}.dropdown-menu-left{right:auto;left:0}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857143;color:#777;white-space:nowrap}.dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{content:"";border-top:0;border-bottom:4px solid}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:2px}@media (min-width:768px){.navbar-right .dropdown-menu{right:0;left:auto}.navbar-right .dropdown-menu-left{right:auto;left:0}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;float:left}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:2}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-bottom-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-right:8px;padding-left:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-right:12px;padding-left:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-top-left-radius:0;border-top-right-radius:0;border-bottom-left-radius:4px}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-top-right-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{display:table-cell;float:none;width:1%}.btn-group-justified>.btn-group .btn{width:100%}.btn-group-justified>.btn-group .dropdown-menu{left:auto}[data-toggle=buttons]>.btn input[type=checkbox],[data-toggle=buttons]>.btn input[type=radio],[data-toggle=buttons]>.btn-group>.btn input[type=checkbox],[data-toggle=buttons]>.btn-group>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*=col-]{float:none;padding-right:0;padding-left:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn,textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn,textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn{height:auto}.input-group .form-control,.input-group-addon,.input-group-btn{display:table-cell}.input-group .form-control:not(:first-child):not(:last-child),.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:400;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type=checkbox],.input-group-addon input[type=radio]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn-group:not(:last-child)>.btn,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:first-child>.btn-group:not(:first-child)>.btn,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle{border-top-left-radius:0;border-bottom-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:active,.input-group-btn>.btn:focus,.input-group-btn>.btn:hover{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{margin-left:-1px}.nav{padding-left:0;margin-bottom:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:focus,.nav>li>a:hover{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#777}.nav>li.disabled>a:focus,.nav>li.disabled>a:hover{color:#777;text-decoration:none;cursor:not-allowed;background-color:transparent}.nav .open>a,.nav .open>a:focus,.nav .open>a:hover{background-color:#eee;border-color:#337ab7}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:focus,.nav-tabs>li.active>a:hover{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:focus,.nav-pills>li.active>a:hover{color:#fff;background-color:#337ab7}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:4px}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{padding-right:15px;padding-left:15px;overflow-x:visible;-webkit-overflow-scrolling:touch;border-top:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1)}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;-webkit-box-shadow:none;box-shadow:none}.navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse{padding-right:0;padding-left:0}}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:340px}@media (max-device-width:480px)and (orientation:landscape){.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:200px}}.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-bottom,.navbar-fixed-top{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){.navbar-fixed-bottom,.navbar-fixed-top{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;height:50px;padding:15px 15px;font-size:18px;line-height:20px}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-brand>img{display:block}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;padding:9px 10px;margin-top:8px;margin-right:15px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;-webkit-box-shadow:none;box-shadow:none}.navbar-nav .open .dropdown-menu .dropdown-header,.navbar-nav .open .dropdown-menu>li>a{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:focus,.navbar-nav .open .dropdown-menu>li>a:hover{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}}.navbar-form{padding:10px 15px;margin-top:8px;margin-right:-15px;margin-bottom:8px;margin-left:-15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1)}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .form-control-static{display:inline-block}.navbar-form .input-group{display:inline-table;vertical-align:middle}.navbar-form .input-group .form-control,.navbar-form .input-group .input-group-addon,.navbar-form .input-group .input-group-btn{width:auto}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .checkbox,.navbar-form .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.navbar-form .checkbox label,.navbar-form .radio label{padding-left:0}.navbar-form .checkbox input[type=checkbox],.navbar-form .radio input[type=radio]{position:relative;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}.navbar-form .form-group:last-child{margin-bottom:0}}@media (min-width:768px){.navbar-form{width:auto;padding-top:0;padding-bottom:0;margin-right:0;margin-left:0;border:0;-webkit-box-shadow:none;box-shadow:none}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-left-radius:0;border-top-right-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{margin-bottom:0;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left;margin-right:15px;margin-left:15px}}@media (min-width:768px){.navbar-left{float:left!important}.navbar-right{float:right!important;margin-right:-15px}.navbar-right~.navbar-right{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:focus,.navbar-default .navbar-brand:hover{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:focus,.navbar-default .navbar-nav>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:focus,.navbar-default .navbar-nav>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:focus,.navbar-default .navbar-nav>.disabled>a:hover{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:focus,.navbar-default .navbar-toggle:hover{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:focus,.navbar-default .navbar-nav>.open>a:hover{color:#555;background-color:#e7e7e7}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-default .btn-link{color:#777}.navbar-default .btn-link:focus,.navbar-default .btn-link:hover{color:#333}.navbar-default .btn-link[disabled]:focus,.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:focus,fieldset[disabled] .navbar-default .btn-link:hover{color:#ccc}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#9d9d9d}.navbar-inverse .navbar-brand:focus,.navbar-inverse .navbar-brand:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a:focus,.navbar-inverse .navbar-nav>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:focus,.navbar-inverse .navbar-nav>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:focus,.navbar-inverse .navbar-nav>.disabled>a:hover{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:focus,.navbar-inverse .navbar-toggle:hover{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:focus,.navbar-inverse .navbar-nav>.open>a:hover{color:#fff;background-color:#080808}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#9d9d9d}.navbar-inverse .navbar-link:hover{color:#fff}.navbar-inverse .btn-link{color:#9d9d9d}.navbar-inverse .btn-link:focus,.navbar-inverse .btn-link:hover{color:#fff}.navbar-inverse .btn-link[disabled]:focus,.navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] .navbar-inverse .btn-link:focus,fieldset[disabled] .navbar-inverse .btn-link:hover{color:#444}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{padding:0 5px;color:#ccc;content:"/\00a0"}.breadcrumb>.active{color:#777}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;margin-left:-1px;line-height:1.42857143;color:#337ab7;text-decoration:none;background-color:#fff;border:1px solid #ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-top-left-radius:4px;border-bottom-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:4px;border-bottom-right-radius:4px}.pagination>li>a:focus,.pagination>li>a:hover,.pagination>li>span:focus,.pagination>li>span:hover{color:#23527c;background-color:#eee;border-color:#ddd}.pagination>.active>a,.pagination>.active>a:focus,.pagination>.active>a:hover,.pagination>.active>span,.pagination>.active>span:focus,.pagination>.active>span:hover{z-index:2;color:#fff;cursor:default;background-color:#337ab7;border-color:#337ab7}.pagination>.disabled>a,.pagination>.disabled>a:focus,.pagination>.disabled>a:hover,.pagination>.disabled>span,.pagination>.disabled>span:focus,.pagination>.disabled>span:hover{color:#777;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-top-left-radius:6px;border-bottom-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:6px;border-bottom-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-top-left-radius:3px;border-bottom-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:3px;border-bottom-right-radius:3px}.pager{padding-left:0;margin:20px 0;text-align:center;list-style:none}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:focus,.pager li>a:hover{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:focus,.pager .disabled>a:hover,.pager .disabled>span{color:#777;cursor:not-allowed;background-color:#fff}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}a.label:focus,a.label:hover{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#777}.label-default[href]:focus,.label-default[href]:hover{background-color:#5e5e5e}.label-primary{background-color:#337ab7}.label-primary[href]:focus,.label-primary[href]:hover{background-color:#286090}.label-success{background-color:#5cb85c}.label-success[href]:focus,.label-success[href]:hover{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:focus,.label-info[href]:hover{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:focus,.label-warning[href]:hover{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:focus,.label-danger[href]:hover{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;background-color:#777;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-group-xs>.btn .badge,.btn-xs .badge{top:0;padding:1px 5px}a.badge:focus,a.badge:hover{color:#fff;text-decoration:none;cursor:pointer}.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#337ab7;background-color:#fff}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding:30px 15px;margin-bottom:30px;color:inherit;background-color:#eee}.jumbotron .h1,.jumbotron h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200}.jumbotron>hr{border-top-color:#d5d5d5}.container .jumbotron,.container-fluid .jumbotron{border-radius:6px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding:48px 0}.container .jumbotron,.container-fluid .jumbotron{padding-right:60px;padding-left:60px}.jumbotron .h1,.jumbotron h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:border .2s ease-in-out;-o-transition:border .2s ease-in-out;transition:border .2s ease-in-out}.thumbnail a>img,.thumbnail>img{margin-right:auto;margin-left:auto}a.thumbnail.active,a.thumbnail:focus,a.thumbnail:hover{border-color:#337ab7}.thumbnail .caption{padding:9px;color:#333}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:700}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable,.alert-dismissible{padding-right:35px}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.progress-bar{float:left;width:0;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#337ab7;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress-bar-striped,.progress-striped .progress-bar{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);-webkit-background-size:40px 40px;background-size:40px 40px}.progress-bar.active,.progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.media{margin-top:15px}.media:first-child{margin-top:0}.media,.media-body{overflow:hidden;zoom:1}.media-body{width:10000px}.media-object{display:block}.media-right,.media>.pull-right{padding-left:10px}.media-left,.media>.pull-left{padding-right:10px}.media-body,.media-left,.media-right{display:table-cell;vertical-align:top}.media-middle{vertical-align:middle}.media-bottom{vertical-align:bottom}.media-heading{margin-top:0;margin-bottom:5px}.media-list{padding-left:0;list-style:none}.list-group{padding-left:0;margin-bottom:20px}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-left-radius:4px;border-top-right-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}a.list-group-item{color:#555}a.list-group-item .list-group-item-heading{color:#333}a.list-group-item:focus,a.list-group-item:hover{color:#555;text-decoration:none;background-color:#f5f5f5}.list-group-item.disabled,.list-group-item.disabled:focus,.list-group-item.disabled:hover{color:#777;cursor:not-allowed;background-color:#eee}.list-group-item.disabled .list-group-item-heading,.list-group-item.disabled:focus .list-group-item-heading,.list-group-item.disabled:hover .list-group-item-heading{color:inherit}.list-group-item.disabled .list-group-item-text,.list-group-item.disabled:focus .list-group-item-text,.list-group-item.disabled:hover .list-group-item-text{color:#777}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{z-index:2;color:#fff;background-color:#337ab7;border-color:#337ab7}.list-group-item.active .list-group-item-heading,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active .list-group-item-heading>small,.list-group-item.active:focus .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading>.small,.list-group-item.active:focus .list-group-item-heading>small,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading>.small,.list-group-item.active:hover .list-group-item-heading>small{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:focus .list-group-item-text,.list-group-item.active:hover .list-group-item-text{color:#c7ddef}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:focus,a.list-group-item-success:hover{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,a.list-group-item-success.active:focus,a.list-group-item-success.active:hover{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:focus,a.list-group-item-info:hover{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,a.list-group-item-info.active:focus,a.list-group-item-info.active:hover{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:focus,a.list-group-item-warning:hover{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,a.list-group-item-warning.active:focus,a.list-group-item-warning.active:hover{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:focus,a.list-group-item-danger:hover{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,a.list-group-item-danger.active:focus,a.list-group-item-danger.active:hover{color:#fff;background-color:#a94442;border-color:#a94442}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05);box-shadow:0 1px 1px rgba(0,0,0,.05)}.panel-body{padding:15px}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-left-radius:3px;border-top-right-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>.small,.panel-title>.small>a,.panel-title>a,.panel-title>small,.panel-title>small>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group,.panel>.panel-collapse>.list-group{margin-bottom:0}.panel>.list-group .list-group-item,.panel>.panel-collapse>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child,.panel>.panel-collapse>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-left-radius:3px;border-top-right-radius:3px}.panel>.list-group:last-child .list-group-item:last-child,.panel>.panel-collapse>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.list-group+.panel-footer{border-top-width:0}.panel>.panel-collapse>.table,.panel>.table,.panel>.table-responsive>.table{margin-bottom:0}.panel>.panel-collapse>.table caption,.panel>.table caption,.panel>.table-responsive>.table caption{padding-right:15px;padding-left:15px}.panel>.table-responsive:first-child>.table:first-child,.panel>.table:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child,.panel>.table:first-child>thead:first-child>tr:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table-responsive:last-child>.table:last-child,.panel>.table:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive,.panel>.table+.panel-body,.panel>.table-responsive+.panel-body{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child td,.panel>.table>tbody:first-child>tr:first-child th{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{margin-bottom:0;border:0}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse>.list-group,.panel-group .panel-heading+.panel-collapse>.panel-body{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ddd}.panel-default>.panel-heading .badge{color:#f5f5f5;background-color:#333}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#337ab7}.panel-primary>.panel-heading{color:#fff;background-color:#337ab7;border-color:#337ab7}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:#337ab7}.panel-primary>.panel-heading .badge{color:#337ab7;background-color:#fff}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#337ab7}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d6e9c6}.panel-success>.panel-heading .badge{color:#dff0d8;background-color:#3c763d}.panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:#bce8f1}.panel-info>.panel-heading .badge{color:#d9edf7;background-color:#31708f}.panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:#faebcc}.panel-warning>.panel-heading .badge{color:#fcf8e3;background-color:#8a6d3b}.panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ebccd1}.panel-danger>.panel-heading .badge{color:#f2dede;background-color:#a94442}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ebccd1}.embed-responsive{position:relative;display:block;height:0;padding:0;overflow:hidden}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-16by9{padding-bottom:56.25%}.embed-responsive-4by3{padding-bottom:75%}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;filter:alpha(opacity=20);opacity:.2}.close:focus,.close:hover{color:#000;text-decoration:none;cursor:pointer;filter:alpha(opacity=50);opacity:.5}button.close{-webkit-appearance:none;padding:0;cursor:pointer;background:0 0;border:0}.modal-open{overflow:hidden}.modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;display:none;overflow:hidden;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transition:-webkit-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out;-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);-o-transform:translate(0,-25%);transform:translate(0,-25%)}.modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);-o-transform:translate(0,0);transform:translate(0,0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #999;border:1px solid rgba(0,0,0,.2);border-radius:6px;outline:0;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5)}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{filter:alpha(opacity=0);opacity:0}.modal-backdrop.in{filter:alpha(opacity=50);opacity:.5}.modal-header{min-height:16.43px;padding:15px;border-bottom:1px solid #e5e5e5}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:15px}.modal-footer{padding:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,.5);box-shadow:0 5px 15px rgba(0,0,0,.5)}.modal-sm{width:300px}}@media (min-width:992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1070;display:block;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:12px;font-weight:400;line-height:1.4;filter:alpha(opacity=0);opacity:0}.tooltip.in{filter:alpha(opacity=90);opacity:.9}.tooltip.top{padding:5px 0;margin-top:-3px}.tooltip.right{padding:0 5px;margin-left:3px}.tooltip.bottom{padding:5px 0;margin-top:3px}.tooltip.left{padding:0 5px;margin-left:-3px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;text-decoration:none;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{right:5px;bottom:0;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{bottom:0;left:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;right:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;left:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:276px;padding:1px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;font-weight:400;line-height:1.42857143;text-align:left;white-space:normal;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2)}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{padding:8px 14px;margin:0;font-size:14px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover>.arrow{border-width:11px}.popover>.arrow:after{content:"";border-width:10px}.popover.top>.arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,.25);border-bottom-width:0}.popover.top>.arrow:after{bottom:1px;margin-left:-10px;content:" ";border-top-color:#fff;border-bottom-width:0}.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,.25);border-left-width:0}.popover.right>.arrow:after{bottom:-10px;left:1px;content:" ";border-right-color:#fff;border-left-width:0}.popover.bottom>.arrow{top:-11px;left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,.25)}.popover.bottom>.arrow:after{top:1px;margin-left:-10px;content:" ";border-top-width:0;border-bottom-color:#fff}.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,.25)}.popover.left>.arrow:after{right:1px;bottom:-10px;content:" ";border-right-width:0;border-left-color:#fff}.carousel{position:relative}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>a>img,.carousel-inner>.item>img{line-height:1}@media all and (transform-3d),(-webkit-transform-3d){.carousel-inner>.item{-webkit-transition:-webkit-transform .6s ease-in-out;-o-transition:-o-transform .6s ease-in-out;transition:transform .6s ease-in-out;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000;perspective:1000}.carousel-inner>.item.active.right,.carousel-inner>.item.next{left:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}.carousel-inner>.item.active.left,.carousel-inner>.item.prev{left:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}.carousel-inner>.item.active,.carousel-inner>.item.next.left,.carousel-inner>.item.prev.right{left:0;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;bottom:0;left:0;width:15%;font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6);filter:alpha(opacity=50);opacity:.5}.carousel-control.left{background-image:-webkit-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.5)),to(rgba(0,0,0,.0001)));background-image:linear-gradient(to right,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);background-repeat:repeat-x}.carousel-control.right{right:0;left:auto;background-image:-webkit-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.0001)),to(rgba(0,0,0,.5)));background-image:linear-gradient(to right,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);background-repeat:repeat-x}.carousel-control:focus,.carousel-control:hover{color:#fff;text-decoration:none;filter:alpha(opacity=90);outline:0;opacity:.9}.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{position:absolute;top:50%;z-index:5;display:inline-block}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{left:50%;margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{right:50%;margin-right:-10px}.carousel-control .icon-next,.carousel-control .icon-prev{width:20px;height:20px;margin-top:-10px;font-family:serif;line-height:1}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;padding-left:0;margin-left:-30%;text-align:center;list-style:none}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;cursor:pointer;background-color:#000 \9;background-color:rgba(0,0,0,0);border:1px solid #fff;border-radius:10px}.carousel-indicators .active{width:12px;height:12px;margin:0;background-color:#fff}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{width:30px;height:30px;margin-top:-15px;font-size:30px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{margin-left:-15px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{margin-right:-15px}.carousel-caption{right:20%;left:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.btn-group-vertical>.btn-group:after,.btn-group-vertical>.btn-group:before,.btn-toolbar:after,.btn-toolbar:before,.clearfix:after,.clearfix:before,.container-fluid:after,.container-fluid:before,.container:after,.container:before,.dl-horizontal dd:after,.dl-horizontal dd:before,.form-horizontal .form-group:after,.form-horizontal .form-group:before,.modal-footer:after,.modal-footer:before,.nav:after,.nav:before,.navbar-collapse:after,.navbar-collapse:before,.navbar-header:after,.navbar-header:before,.navbar:after,.navbar:before,.pager:after,.pager:before,.panel-body:after,.panel-body:before,.row:after,.row:before{display:table;content:" "}.btn-group-vertical>.btn-group:after,.btn-toolbar:after,.clearfix:after,.container-fluid:after,.container:after,.dl-horizontal dd:after,.form-horizontal .form-group:after,.modal-footer:after,.nav:after,.navbar-collapse:after,.navbar-header:after,.navbar:after,.pager:after,.panel-body:after,.row:after{clear:both}.center-block{display:block;margin-right:auto;margin-left:auto}.pull-right{float:right!important}.pull-left{float:left!important}.hide{display:none!important}.show{display:block!important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none!important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-lg,.visible-md,.visible-sm,.visible-xs{display:none!important}.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block{display:none!important}@media (max-width:767px){.visible-xs{display:block!important}table.visible-xs{display:table}tr.visible-xs{display:table-row!important}td.visible-xs,th.visible-xs{display:table-cell!important}}@media (max-width:767px){.visible-xs-block{display:block!important}}@media (max-width:767px){.visible-xs-inline{display:inline!important}}@media (max-width:767px){.visible-xs-inline-block{display:inline-block!important}}@media (min-width:768px)and (max-width:991px){.visible-sm{display:block!important}table.visible-sm{display:table}tr.visible-sm{display:table-row!important}td.visible-sm,th.visible-sm{display:table-cell!important}}@media (min-width:768px)and (max-width:991px){.visible-sm-block{display:block!important}}@media (min-width:768px)and (max-width:991px){.visible-sm-inline{display:inline!important}}@media (min-width:768px)and (max-width:991px){.visible-sm-inline-block{display:inline-block!important}}@media (min-width:992px)and (max-width:1199px){.visible-md{display:block!important}table.visible-md{display:table}tr.visible-md{display:table-row!important}td.visible-md,th.visible-md{display:table-cell!important}}@media (min-width:992px)and (max-width:1199px){.visible-md-block{display:block!important}}@media (min-width:992px)and (max-width:1199px){.visible-md-inline{display:inline!important}}@media (min-width:992px)and (max-width:1199px){.visible-md-inline-block{display:inline-block!important}}@media (min-width:1200px){.visible-lg{display:block!important}table.visible-lg{display:table}tr.visible-lg{display:table-row!important}td.visible-lg,th.visible-lg{display:table-cell!important}}@media (min-width:1200px){.visible-lg-block{display:block!important}}@media (min-width:1200px){.visible-lg-inline{display:inline!important}}@media (min-width:1200px){.visible-lg-inline-block{display:inline-block!important}}@media (max-width:767px){.hidden-xs{display:none!important}}@media (min-width:768px)and (max-width:991px){.hidden-sm{display:none!important}}@media (min-width:992px)and (max-width:1199px){.hidden-md{display:none!important}}@media (min-width:1200px){.hidden-lg{display:none!important}}.visible-print{display:none!important}@media print{.visible-print{display:block!important}table.visible-print{display:table}tr.visible-print{display:table-row!important}td.visible-print,th.visible-print{display:table-cell!important}}.visible-print-block{display:none!important}@media print{.visible-print-block{display:block!important}}.visible-print-inline{display:none!important}@media print{.visible-print-inline{display:inline!important}}.visible-print-inline-block{display:none!important}@media print{.visible-print-inline-block{display:inline-block!important}}@media print{.hidden-print{display:none!important}}
}}
<div class="c_pluginX" data-url="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js">
</div>
<div class="c_pluginX" data-url="https://code.jquery.com/jquery-2.1.3.min.js">
</div>
<div class="c_pluginX" data-url="{{fullurl: {{#rel2abs: 사용자:Senouis/자바스크립트/plugin1.js}}|action=raw}}">
</div>

2020년 1월 15일 (수) 15:47 기준 최신판

//---------------------------------------------------------------------------------------------
// UncycloEngine 1 by Epic Ungames, 2019-2020
//---------------------------------------------------------------------------------------------

//----------------------------------mapinfo and object definition------------------------------
// Objects must also be defined in server-side javascript
function GameRule(RedClock, BlueClock, initialstate) {
	this.state = initialstate; // 0: game ceased, 1: game setup, 2: game on!, 3: round end
	this.RedClock = RedClock;
	this.BlueClock = BlueClock;
	this.currentdominating = 0; // 0: neutral, 1: red, 2:blue
	this.reddominatingprogress = 0;
	this.bluedominatingprogress = 0;
}

let redteamnum = 0;
let blueteamnum = 0;

function GameObject (pos, size, direction, team, collidetype, flag, health = 100) { 
	// pos: array[x, y], size: array(cube)[x, y]/integer(cylinder), direction: integer(degree)
	this.pos = pos;
	this.size = size;
	this.rotation = [0, 0 ,0];
	this.direction = direction; // define camera angle
	this.height = 0;
	this.scale = [1, 1, 1];
	this.collidetype = collidetype; // 0: statical cubic(no direction), 1: cylinder
	this.flag = flag; // free flag
	this.team = team; // team : integer(0: not defined, 1: Red Yangachi, 2: Blue Yingeo, 3: Neutral)
	this.state = 0; // state depends on type of Game Object(0 is usually initial state)
	this.healthpoint = health;
	this.maxhealthpoint = health;
	this.canbedamaged = false;
	this.cameraMatrix = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
	this.cameraAngleRadians = 0;
	this.updateCameraAngle = (event, value) => {
		this.cameraAngleRadians = degToRad(value);
	 };
	this.updatePosition = (index, value)=> {
		switch (index) {
			case 0:
				this.pos[0] = value;
				break;
			case 2:
				this.pos[1] = value;
				break;
			case 1:
				this.height = value;
				break;
			default:
				break;
		}
	  };
	this.vertexlist = [ 
			// wall 1
			2*pos[0],   32,  2*pos[1],
			2*pos[0],   -32,  2*pos[1],
			2*pos[0],   -32,  2*pos[1] + 2*size[1],
			2*pos[0],   32,  2*pos[1],
			2*pos[0],   -32,  2*pos[1] + 2*size[1],
			2*pos[0],   32, 2*pos[1] + 2*size[1],
			// wall 2
			2*pos[0]+ 2*size[0],   32,  2*pos[1],
			2*pos[0]+ 2*size[0],   -32,  2*pos[1] + 2*size[1],
			2*pos[0]+ 2*size[0],   -32,  2*pos[1],
			2*pos[0]+ 2*size[0],   32,  2*pos[1],
			2*pos[0]+ 2*size[0],   32,  2*pos[1] + 2*size[1],
			2*pos[0]+ 2*size[0],   -32,  2*pos[1] + 2*size[1],
			// wall 3
			2*pos[0],		32,  2*pos[1],
			2*pos[0]+ 2*size[0],	-32,  2*pos[1],
			2*pos[0],		-32,  2*pos[1],
			2*pos[0],		32,  2*pos[1],
			2*pos[0]+ 2*size[0],	32,  2*pos[1],
			2*pos[0]+ 2*size[0], -32,  2*pos[1],
			// wall 4
			2*pos[0],		32,  2*pos[1] + 2*size[1],
			2*pos[0],		-32,  2*pos[1] + 2*size[1],
			2*pos[0]+ 2*size[0],	-32,  2*pos[1] + 2*size[1],
			2*pos[0],		32,  2*pos[1] + 2*size[1],
			2*pos[0]+ 2*size[0], -32,  2*pos[1] + 2*size[1],
			2*pos[0]+ 2*size[0],	32,  2*pos[1] + 2*size[1]
		];
	this.updateRotation = (index, value) => {
		var angleInDegrees = value;
		var angleInRadians = (angleInDegree % 360) * Math.PI / 180;
		this.rotation[index] = angleInRadians;
	  };

	this.updatescale = (index, value) =>{
		  this.scale[index] = value;
	  };
	this.GetCenterPosition = () => {
		if (this.collidetype === 0) {
			return [this.pos[0] + this.size[0] /2, this.pos[1] + this.size[1] / 2];
		} else {
			return [this.pos[0] + this.size, this.pos[1] + this.size];
		}
	};
	this.SetCenterPosition = (position) => {
		if (this.collidetype === 0) {
			this.pos = [position[0] -this.size[0] /2, position[1] -this.size[1] / 2];
		} else {
			this.pos = [position[0] -this.size, position[1] - this.size];
		}
	};
	this.IsColliding = (target) => {
		if (this.collidetype === 0 && target.collidetype === 0) { // cube vs cube
			if (this.GetCenterPosition()[0] + this.size[0]/2 >= target.GetCenterPosition()[0] - target.size[0]/2 && this.GetCenterPosition()[0] - this.size[0]/2 <= target.GetCenterPosition()[0] + target.size[0]/2 && this.GetCenterPosition()[1] + this.size[1]/2 >= target.GetCenterPosition()[1] - target.size[1]/2 && this.GetCenterPosition()[1] - this.size[1]/2 <= target.GetCenterPosition()[1] + target.size[1]/2) return true;
			else return false;
		} else if (this.collidetype === 0 && target.collidetype === 1) {
			if (target.GetCenterPosition()[0] + target.size >= this.GetCenterPosition()[0] - this.size[0] / 2 && target.GetCenterPosition()[0] - target.size <= this.GetCenterPosition()[0] + this.size[0] / 2) { // horizontal collision
				if (target.GetCenterPosition()[1] >= this.GetCenterPosition()[1] - this.size[1]/2 - target.size && target.GetCenterPosition()[1] <= this.GetCenterPosition()[1] + this.size[1]/2 + target.size ) 	return true;
			}
			if (target.GetCenterPosition()[1] + target.size >= this.GetCenterPosition()[1] - this.size[1] /2 && target.GetCenterPosition()[1] - target.size <= this.GetCenterPosition()[1] + this.size[1] /2) {
				// vertical collision
				if (target.GetCenterPosition()[0]+ target.size >= this.GetCenterPosition()[0] - this.size[0]/2 && target.GetCenterPosition()[0] - target.size <= this.GetCenterPosition()[0] + this.size[0] /2) {
					return true;
				}
			}
			// corner collision
			let equation1 = (target.GetCenterPosition()[0]-(this.GetCenterPosition()[0] - this.size[0] / 2)) * (target.GetCenterPosition()[0]-(this.GetCenterPosition()[0]- this.size[0] / 2))+ (target.GetCenterPosition()[1]-(this.GetCenterPosition()[1]- this.size[1] / 2)) * (target.GetCenterPosition()[1]-(this.GetCenterPosition()[1]- this.size[1] / 2));
			let equation2 = (target.GetCenterPosition()[0]-(this.GetCenterPosition()[0] - this.size[0] / 2)) * (target.GetCenterPosition()[0]-(this.GetCenterPosition()[0]- this.size[0] / 2))+ (target.GetCenterPosition()[1]-(this.GetCenterPosition()[1]+this.size[1]/2)) * (target.GetCenterPosition()[1]-(this.GetCenterPosition()[1]+this.size[1]/2));
			let equation3 = (target.GetCenterPosition()[0]-(this.GetCenterPosition()[0]+this.size[0]/2)) * (target.GetCenterPosition()[0]-(this.GetCenterPosition()[0]+this.size[0]/2))+ (target.GetCenterPosition()[1]-(this.GetCenterPosition()[1]- this.size[1] / 2)) * (target.GetCenterPosition()[1]-(this.GetCenterPosition()[1]- this.size[1] / 2));
			let equation4 = (target.GetCenterPosition()[0]-this.GetCenterPosition()[0]-this.size[0]/2) * (target.GetCenterPosition()[0]-this.GetCenterPosition()[0]-this.size[0]/2)+ (target.GetCenterPosition()[1]-this.GetCenterPosition()[1]-this.size[1]/2) * (target.GetCenterPosition()[1]-this.GetCenterPosition()[1]-this.size[1]/2);
			if (equation1 <= target.size* target.size || equation2 <= target.size* target.size || equation3 <= target.size* target.size || equation4 <= target.size* target.size) {
				return true;
			} else {
				return false;
			}
		} else if (this.collidetype === 1 && target.collidetype === 0) {
			if (this.GetCenterPosition()[0] + this.size >= target.GetCenterPosition()[0] - target.size[0] / 2 && this.GetCenterPosition()[0] - this.size <= target.GetCenterPosition()[0] + target.size[0]/2) { // horizontal collision
				if (this.GetCenterPosition()[1] + this.size>= target.GetCenterPosition()[1] - target.size[1] / 2 && this.GetCenterPosition()[1] - this.size <= target.GetCenterPosition()[1] + target.size[1]/2 ) return true;
			}
			if (this.GetCenterPosition()[1] + this.size >= target.GetCenterPosition()[1] - target.size[1] / 2 && this.GetCenterPosition()[1] - this.size <= target.GetCenterPosition()[1] + target.size[1]/2 ) {
				// vertical collision
				if (this.GetCenterPosition()[0] + this.size>= target.GetCenterPosition()[0] - target.size[0] / 2  && this.GetCenterPosition()[0]- this.size <= target.GetCenterPosition()[0] + target.size[0] /2) {
					return true;
				}
			}
			// corner collision
			let equation1 = (this.GetCenterPosition()[0]-(target.GetCenterPosition()[0]+target.size[0]/2)) * (this.GetCenterPosition()[0]-(target.GetCenterPosition()[0]+target.size[0]/2))+ (this.GetCenterPosition()[1]-(target.GetCenterPosition()[1]+target.size[1]/2)) * (this.GetCenterPosition()[1]-(target.GetCenterPosition()[1]+target.size[1]/2));
			let equation2 = (this.GetCenterPosition()[0]-(target.GetCenterPosition()[0] - target.size[0] / 2)) * (this.GetCenterPosition()[0]-(target.GetCenterPosition()[0]- target.size[0] / 2))+ (this.GetCenterPosition()[1]-(target.GetCenterPosition()[1]+target.size[1]/2)) * (this.GetCenterPosition()[1]-(target.GetCenterPosition()[1]+target.size[1]/2));
			let equation3 = (this.GetCenterPosition()[0]-(target.GetCenterPosition()[0]+target.size[0]/2)) * (this.GetCenterPosition()[0]-(target.GetCenterPosition()[0]+target.size[0]/2))+ (this.GetCenterPosition()[1]-(target.GetCenterPosition()[1] - target.size[1] / 2)) * (this.GetCenterPosition()[1]-(target.GetCenterPosition()[1] - target.size[1] / 2));
			let equation4 = (this.GetCenterPosition()[0]-(target.GetCenterPosition()[0] - target.size[0] / 2)) * (this.GetCenterPosition()[0]-(target.GetCenterPosition()[0] - target.size[0] / 2))+ (this.GetCenterPosition()[1]-(target.GetCenterPosition()[1]- target.size[1] / 2)) * (this.GetCenterPosition()[1]-(target.GetCenterPosition()[1]- target.size[1] / 2));
			if (equation1 <= this.size* this.size || equation2 <= this.size* this.size || equation3 <= this.size* this.size || equation4 <= this.size* this.size) {
				return true;
			} else {
				return false;
			}
		} else { // cylinder vs cylinder
			if ((this.GetCenterPosition()[0] - target.GetCenterPosition()[0])*(this.GetCenterPosition()[0] - target.GetCenterPosition()[0]) + (this.GetCenterPosition()[1] - target.GetCenterPosition()[1])*(this.GetCenterPosition()[1] - target.GetCenterPosition()[1]) <= (this.size + target.size) * (this.size + target.size)) return true;
			else return false;
		}
		return false; // this could not be happened
	};
}
function Projectile(pos, size, direction, team,  shooter, imgsrc, type = 0) {
	GameObject.call(this, pos, size, direction, team, 1, 0, 1);
	this.movespeed = 4;
	this.shooter = shooter;
	this.imgsrc = imgsrc;
	this.visible = false;
	this.type = type;
	this.cameraMatrix = m4.lookAt([this.GetCenterPosition()[0],0,this.GetCenterPosition()[1]],[this.GetCenterPosition()[0]+Math.cos(this.direction), 0, this.GetCenterPosition()[1]+Math.sin(this.direction)], up );
	this.vertexlist = [
	];
}
Projectile.prototype = Object.create(GameObject.prototype);
Projectile.prototype.constructor = Projectile;
const MAX_PROJECTILE_PER_PLAYER = 100;
const MAX_PROJECTILE_NUMBER = 100 * MAX_PROJECTILE_PER_PLAYER;
let projectilelist = [];

function Explosion(pos, size, type = 0) {
	GameObject.call(this, pos, size, 0, 0, 1, 0, 1);
	this.type = type;
	this.counter = 0;
	this.active = true;
	this.cameraMatrix = m4.lookAt([this.GetCenterPosition()[0],0,this.GetCenterPosition()[1]],[this.GetCenterPosition()[0]+Math.cos(this.direction), 0, this.GetCenterPosition()[1]+Math.sin(this.direction)], up );
	this.vertexlist = GeneratePlaneVertex(this.GetCenterPosition(), size * 2, this.cameraMatrix);
}
Explosion.prototype = Object.create(GameObject.prototype);
Explosion.prototype.constructor = Explosion;

const MAX_EXPLOSION_NUMBER = 100 * MAX_PROJECTILE_PER_PLAYER;
let explosionlist = [];
function Player(pos, size, direction, team, health, id = 0, isdead = false, playername = "unknown player", classnum = 0) {
	GameObject.call(this, pos, size, direction, team, 1, 0, health);
	this.playername = playername;
	this.playerID = id;
	this.movespeed = 1;
	this.classnumber = classnum;
	this.canbedamaged = true;
	this.isdead = isdead;
	this.deadtimer;
	this.secondweapon = undefined; // weapon 0
	this.firstweapon = undefined; // weapon 1
	this.currentweapon = 0;
	this.ReloadWeapon = () => {
		console.log("Reloaded");
	};
	this.FireWeapon = () =>{
		console.log("Fired");
	};
	this.DoSpecialSkill = () => {
		console.log("Did SpecialSkill");
	};
	this.ReleaseFire = () => {
		return;
	}
	this.reloadDelaying = false;
	this.raylist = []; // remember, this only has MAX_RAY_PER_PLAYER number of elements
	this.moveSomething = () => {
		let camMatrix = m4.lookAt([this.GetCenterPosition()[0],this.height,this.GetCenterPosition()[1]],[this.GetCenterPosition()[0]+Math.cos(this.direction), 0, this.GetCenterPosition()[1]+Math.sin(this.direction)], up );
		let forwardvector = m4.getForward(camMatrix);
		let rightvector = m4.getRight(camMatrix);
		if (keystate[0] && keystate[2] || keystate[0] && keystate[3] || keystate[1] && keystate[2] || keystate[1] && keystate[3]) {
			rightvector[0] *= 0.7071;
			rightvector[2] *= 0.7071;
			forwardvector[0] *= 0.7071;
			forwardvector[2] *= 0.7071;
		}
		// remember, the map has reversed axis
		if (keystate[0]){ // a
			let freeToMove = true;
			for (let mapobject of mapinfo.mapobjectlist) {
				let tempmapobject = new GameObject([mapobject.pos[0] - this.movespeed*rightvector[0], mapobject.pos[1] ], mapobject.size, mapobject.direction, mapobject.team, mapobject.collidetype, mapobject.flag, mapobject.healthpoint);
				if (tempmapobject.team != this.team && this.IsColliding(tempmapobject)) freeToMove = false;
			}
			if (freeToMove){
				this.updatePosition(0, this.pos[0] + this.movespeed*rightvector[0]);
				
			}
			freeToMove = true;
			for (let mapobject of mapinfo.mapobjectlist) {
				let tempmapobject = new GameObject([mapobject.pos[0], mapobject.pos[1] - this.movespeed*rightvector[2]], mapobject.size, mapobject.direction, mapobject.team, mapobject.collidetype, mapobject.flag, mapobject.healthpoint);
				if (tempmapobject.team != this.team &&this.IsColliding(tempmapobject)) freeToMove = false;
			}
			if (freeToMove){
				this.updatePosition(2, this.pos[1] + this.movespeed*rightvector[2]);
			}
			ws.send(JSON.stringify({
				type:5,
				id: this.playerID,
				pos: this.pos,
				direction: this.direction
			}));
		}
		if (keystate[1]){ //d
			let freeToMove = true;
			for (let mapobject of mapinfo.mapobjectlist) {
				let tempmapobject = new GameObject([mapobject.pos[0] + this.movespeed*rightvector[0], mapobject.pos[1] ], mapobject.size, mapobject.direction, mapobject.team, mapobject.collidetype, mapobject.flag, mapobject.healthpoint);
				if (tempmapobject.team != this.team &&this.IsColliding(tempmapobject)) freeToMove = false;
			}
			if (freeToMove){
				this.updatePosition(0, this.pos[0] - this.movespeed*rightvector[0]);
				
			}
			freeToMove = true;
			for (let mapobject of mapinfo.mapobjectlist) {
				let tempmapobject = new GameObject([mapobject.pos[0], mapobject.pos[1] + this.movespeed*rightvector[2]], mapobject.size, mapobject.direction, mapobject.team, mapobject.collidetype, mapobject.flag, mapobject.healthpoint);
				if (tempmapobject.team != this.team &&this.IsColliding(tempmapobject)) freeToMove = false;
			}
			if (freeToMove){
				this.updatePosition(2, this.pos[1] - this.movespeed*rightvector[2]);
			}
			ws.send(JSON.stringify({
				type:5,
				id: this.playerID,
				pos: this.pos,
				direction: this.direction
			}));
		}
		if (keystate[2]) { //s
			let freeToMove = true;
			for (let mapobject of mapinfo.mapobjectlist) {
				let tempmapobject = new GameObject([mapobject.pos[0] - this.movespeed*forwardvector[0], mapobject.pos[1] ], mapobject.size, mapobject.direction, mapobject.team, mapobject.collidetype, mapobject.flag, mapobject.healthpoint);
				if (tempmapobject.team != this.team &&this.IsColliding(tempmapobject)) freeToMove = false;
			}
			if (freeToMove){
				this.updatePosition(0, this.pos[0] + this.movespeed*forwardvector[0]);
			}
			freeToMove = true;
			for (let mapobject of mapinfo.mapobjectlist) {
				let tempmapobject = new GameObject([mapobject.pos[0], mapobject.pos[1] - this.movespeed*forwardvector[2]], mapobject.size, mapobject.direction, mapobject.team, mapobject.collidetype, mapobject.flag, mapobject.healthpoint);
				if (tempmapobject.team != this.team &&this.IsColliding(tempmapobject)) freeToMove = false;
			}
			if (freeToMove){
				this.updatePosition(2, this.pos[1] + this.movespeed*forwardvector[2]);
			}
			ws.send(JSON.stringify({
				type:5,
				id: this.playerID,
				pos: this.pos,
				direction: this.direction
			}));
		}
		if (keystate[3]) { // w
			let freeToMove = true;
			for (let mapobject of mapinfo.mapobjectlist) {
				let tempmapobject = new GameObject([mapobject.pos[0] + this.movespeed*forwardvector[0], mapobject.pos[1] ], mapobject.size, mapobject.direction, mapobject.team, mapobject.collidetype, mapobject.flag, mapobject.healthpoint);
				if (tempmapobject.team != this.team &&this.IsColliding(tempmapobject)) freeToMove = false;
			}
			if (freeToMove){
				this.updatePosition(0, this.pos[0] -this.movespeed*forwardvector[0]);
			}
			freeToMove = true;
			for (let mapobject of mapinfo.mapobjectlist) {
				let tempmapobject = new GameObject([mapobject.pos[0], mapobject.pos[1] + this.movespeed*forwardvector[2]], mapobject.size, mapobject.direction, mapobject.team, mapobject.collidetype, mapobject.flag, mapobject.healthpoint);
				if (tempmapobject.team != this.team &&this.IsColliding(tempmapobject)) freeToMove = false;
			}
			if (freeToMove){
				this.updatePosition(2, this.pos[1] - this.movespeed*forwardvector[2]);
			}
			ws.send(JSON.stringify({
				type:5,
				id: this.playerID,
				pos: this.pos,
				direction: this.direction
			}));
		}
		if (keystate[0] || keystate[1] || keystate[2] || keystate[3]) {
			if ( heightcount >= 0 && heightcount <20) this.updatePosition(1, 0.1* heightcount);
			else this.updatePosition(1, 2-0.1*heightcount);
			if (heightcount >= 39) heightcount = 0;
			else heightcount = heightcount +1;
		}
		if (keystate[4] && this.reloadDelaying === false) { // q
			if (this.currentweapon === 0) {
				this.secondweapon.isFiring = false;
				this.currentweapon = 1;
			} else {
				this.firstweapon.isFiring = false;
				this.currentweapon = 0;
			}
			ws.send(JSON.stringify({
				type:16,
				id: this.playerID,
				currentweapon: this.currentweapon
			}));
			this.reloadDelaying = true;
			setTimeout(this.keydelayEnd,400);
		}
		if (keystate[5]) { // e
		}
		if (keystate[6]) { // r
			this.ReloadWeapon();
		}
		if (keystate[7]) { // f
			
		}
	  }
	this.keydelayEnd = () => {
			this.reloadDelaying = false;
		}
	this.vertexlist = GeneratePlaneVertex(this.GetCenterPosition(), 32, this.cameraMatrix);
}
Player.prototype = Object.create(GameObject.prototype);
Player.prototype.constructor = Player;
let playerlist = [];
function Building(pos, size, direction, team, health, id = 0) {
	Player.call(this, pos, size, direction, team, health, id)
}
Building.prototype = Object.create(Player.prototype);
Building.prototype.constructor = Building;
const mapobjectsizeconstant = 32;
function MapInfo (text) { // map infomation
	  this.rawmapdata = text;
	  let mapdataarray = this.rawmapdata.split('\n');
	  let mapsize = mapdataarray[0].split(' ');
	  this.mapheight = parseInt(mapsize[0]);
	  this.mapwidth = parseInt(mapsize[1]);
	  this.mapversion = parseInt(mapsize[2]);
	  this.mapdata = mapdataarray;
	  this.mapwallcounter = 0;
	  this.mapobjectlist = [];
	  this.maphealthkitlist = [];
	  let mapX = 64* this.mapwidth;
	  let mapY = 64* this.mapheight;
	  this.polygons = [
			  // ground
			  0,   -32,  0,
			  mapX,   -32,  mapY,
			  mapX,   -32,  0,
			  mapX,   -32,  mapY,
			  0,   -32,  0,
			  0,   -32,  mapY,

			  // ceiling
			  0,   32,  0,
			  mapX,   32,  0,
			  mapX,   32,  mapY,
			  mapX,   32,  mapY,
			  0,   32,  mapY,
			  0,   32,  0
			  
			  // walls
			  
			  ];
	  this.mapColors = [
        // ground and ceiling
        0,	0,	0,
        0,	0,	0,
        0,	0,	0,
        0,	0,	0,
        0,	0,	0,
        0,	0,	0,

        0,	0,	0,
        0,	0,	0,
        0,	0,	0,
        0,	0,	0,
        0,	0,	0,
        0,	0,	0
        
        // other wall
		];
	  for (let i = 1; i <= this.mapheight; i++) {
		for (let j = 0; j < this.mapwidth; j++){
			switch (this.mapdata[i][j]) {
				case 'R':
					this.RedSpawn = [ mapobjectsizeconstant*j,  mapobjectsizeconstant*(i-1)];
					break;
				case 'B':
					this.BlueSpawn = [ mapobjectsizeconstant*j, mapobjectsizeconstant*(i-1)];
					break;
				case 'W':
					this.mapobjectlist.push(new GameObject([mapobjectsizeconstant*j, mapobjectsizeconstant*(i-1)], [mapobjectsizeconstant, mapobjectsizeconstant],0, 0, 0, 0)); 
					break;
				case 'Q':
					this.mapobjectlist.push(new GameObject([mapobjectsizeconstant*j, mapobjectsizeconstant*(i-1)], [mapobjectsizeconstant, mapobjectsizeconstant],0, 0, 0, 2)); 
					break;
				case 'A':
					this.mapobjectlist.push(new GameObject([mapobjectsizeconstant*j, mapobjectsizeconstant*(i-1)], [mapobjectsizeconstant, mapobjectsizeconstant],0, 0, 0, 1)); 
					break;
				case 'H':
					this.maphealthkitlist.push(new Healthkit([mapobjectsizeconstant*j + 8, mapobjectsizeconstant*(i-1) +8], 8, this.maphealthkitlist.length));
					break;
				case 'Z':
					this.mapobjectlist.push(new Door([mapobjectsizeconstant*j, mapobjectsizeconstant*(i-1)], [mapobjectsizeconstant, mapobjectsizeconstant],270, 2));
					break;
				case 'X':
					this.mapobjectlist.push(new Door([mapobjectsizeconstant*j, mapobjectsizeconstant*(i-1)], [mapobjectsizeconstant, mapobjectsizeconstant],90, 2));
					break;
				case 'C':
					this.mapobjectlist.push(new Door([mapobjectsizeconstant*j, mapobjectsizeconstant*(i-1)], [mapobjectsizeconstant, mapobjectsizeconstant],180, 2));
					break;
				case 'V':
					this.mapobjectlist.push(new Door([mapobjectsizeconstant*j, mapobjectsizeconstant*(i-1)], [mapobjectsizeconstant, mapobjectsizeconstant],0, 2));
					break;
				case 'U':
					this.mapobjectlist.push(new Door([mapobjectsizeconstant*j, mapobjectsizeconstant*(i-1)], [mapobjectsizeconstant, mapobjectsizeconstant],270, 1));
					break;
				case 'I':
					this.mapobjectlist.push(new Door([mapobjectsizeconstant*j, mapobjectsizeconstant*(i-1)], [mapobjectsizeconstant, mapobjectsizeconstant],90, 1));
					break;
				case 'O':
					this.mapobjectlist.push(new Door([mapobjectsizeconstant*j, mapobjectsizeconstant*(i-1)], [mapobjectsizeconstant, mapobjectsizeconstant],180, 1));
					break;
				case 'P':
					this.mapobjectlist.push(new Door([mapobjectsizeconstant*j, mapobjectsizeconstant*(i-1)], [mapobjectsizeconstant, mapobjectsizeconstant],0, 1));
					break;
				default:
					break; // do nothing
			}
		}
	  }
	  for (let object of this.mapobjectlist) {
		  if (object.constructor === GameObject) {
			  this.mapwallcounter += 4;
		  } else if (object.constructor === Door) {
			  this.mapwallcounter += 2;
		  }
		  this.polygons = this.polygons.concat(object.vertexlist);
	  }
}
function Healthkit(pos, size, id) {
	GameObject.call(this, pos, size, 0, 0, 1, 1, 0);
	this.id = id;
	this.respawntime = 8000;
	this.isSpawned = true;
	this.respawntimer = undefined;
	this.vertexlist = GenerateProjectile(this.GetCenterPosition(), size, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]);
	this.respawn = () => {
		this.isSpawned = true;
		return;
	}
}
Healthkit.prototype = Object.create(GameObject.prototype);
Healthkit.prototype.constructor = Healthkit;

function Door(pos, size, direction, team) {
	GameObject.call(this, pos, size, direction, team, 0, 0, 100000);
	switch (direction) {
		case 0:
			this.vertexlist = [ 
			// wall (right)
			2*pos[0] + 2* size[0],   32,  2*pos[1],
			2*pos[0] + 2* size[0],   -32,  2*pos[1]+2*size[1],
			2*pos[0] + 2* size[0],   -32,  2*pos[1],
			2*pos[0] + 2* size[0],   32,  2*pos[1],
			2*pos[0] + 2* size[0],   32,  2*pos[1]+2*size[1],
			2*pos[0] + 2* size[0],   -32,  2*pos[1]+2*size[1],
			// wall (left)
			2*pos[0] + 2* size[0] - 4,   32,  2*pos[1],
			2*pos[0] + 2* size[0] - 4,   -32,  2*pos[1],
			2*pos[0] + 2* size[0] - 4,   -32,  2*pos[1]+2*size[1],
			2*pos[0] + 2* size[0] - 4,   32,  2*pos[1],
			2*pos[0] + 2* size[0] - 4,   -32,  2*pos[1]+2*size[1],
			2*pos[0] + 2* size[0] - 4,   32,  2*pos[1]+2*size[1]
			];
			break;
		case 90:
			this.vertexlist = [
			// wall (down)
			2*pos[0],		32,  2*pos[1]+2*size[1],
			2*pos[0],		-32,  2*pos[1]+2*size[1],
			2*pos[0] + 2* size[0],	-32,  2*pos[1]+2*size[1],
			2*pos[0],		32,  2*pos[1]+2*size[1],
			2*pos[0] + 2* size[0], -32,  2*pos[1]+2*size[1],
			2*pos[0] + 2* size[0],	32,  2*pos[1]+2*size[1],
			// wall (Up)
			2*pos[0],		32,  2*pos[1]+2*size[1]-4,
			2*pos[0] + 2* size[0],	-32, 2*pos[1]+2*size[1]-4,
			2*pos[0],		-32,  2*pos[1]+2*size[1]-4,
			2*pos[0],		32,  2*pos[1]+2*size[1]-4,
			2*pos[0] + 2* size[0],	32,  2*pos[1]+2*size[1]-4,
			2*pos[0] + 2* size[0], -32,  2*pos[1]+2*size[1]-4
			];
			break;
		case 180:
			this.vertexlist = [
			// wall (left)
			2*pos[0],   32,  2*pos[1],
			2*pos[0],   -32,  2*pos[1],
			2*pos[0],   -32,  2*pos[1]+2*size[1],
			2*pos[0],   32,  2*pos[1],
			2*pos[0],   -32,  2*pos[1]+2*size[1],
			2*pos[0],   32,  2*pos[1]+2*size[1], 
			// wall (right)
			2*pos[0] + 4,   32,  2*pos[1],
			2*pos[0] + 4,   -32,  2*pos[1]+2*size[1],
			2*pos[0] + 4,   -32,  2*pos[1],
			2*pos[0] + 4,   32,  2*pos[1],
			2*pos[0] + 4,   32,  2*pos[1]+2*size[1],
			2*pos[0] + 4,   -32,  2*pos[1]+2*size[1],
			];
			break;
		case 270:
			this.vertexlist = [
			// wall (Up)
			2*pos[0],		32,  2*pos[1],
			2*pos[0] + 2* size[0],	-32,  2*pos[1],
			2*pos[0],		-32,  2*pos[1],
			2*pos[0],		32,  2*pos[1],
			2*pos[0] + 2* size[0],	32,  2*pos[1],
			2*pos[0] + 2* size[0], -32,  2*pos[1],
			// wall (down)
			2*pos[0],		32,  2*pos[1]+4,
			2*pos[0],		-32,  2*pos[1]+4,
			2*pos[0] + 2* size[0],	-32,  2*pos[1]+4,
			2*pos[0],		32,  2*pos[1]+4,
			2*pos[0] + 2* size[0], -32,  2*pos[1]+4,
			2*pos[0] + 2* size[0],	32,  2*pos[1]+4
			];
			break;
		default:
			break;
	}
}
Door.prototype = Object.create(GameObject.prototype);
Door.prototype.constructor = Door;

function AreaEquation(centerpos, firstcornerpos, secondcornerpos) { // 3 dimensional position
	this.point = centerpos;
	this.normalvector = m4.cross([centerpos[0]-firstcornerpos[0],centerpos[1]-firstcornerpos[1],centerpos[2]-firstcornerpos[2]], [centerpos[0]-secondcornerpos[0],centerpos[1]-secondcornerpos[1],centerpos[2]-secondcornerpos[2]]);
}
function LineEquation(startpos, endpos) { // 3 dimensional position
	this.point = startpos;
	this.linevector = [endpos[0] - startpos[0],endpos[1] - startpos[1],endpos[2] - startpos[2]];
}
function CylinderEquation(center, radius) {
	this.centerpos = center;
	this.radius = radius;
}
const MAX_RAY_PER_PLAYER = 10;
const MAX_RAY_NUM = 32 * MAX_RAY_PER_PLAYER;
function Ray (startpos, endpos) {
	this.visible = false;
	this.startpos = startpos; // array
	this.endpos = endpos; // array
	this.collidedobjectsinfo = []; // will contain list of GameObject objects and their penetrated positions
	this.AddPenetratingObjects = (objectlist) => {
		for (let object of objectlist){
			let lineeq = new LineEquation(this.startpos, this.endpos);
			if (object.collidetype === 0) { // cubic -> doing collision check 4 times
				let areaeq1 = new AreaEquation([object.GetCenterPosition()[0]-object.size[0]/2, object.GetCenterPosition()[1],0], [object.GetCenterPosition()[0]-object.size[0]/2, object.GetCenterPosition()[1]-object.size[1]/2,mapobjectsizeconstant/2],[object.GetCenterPosition()[0]-object.size[0]/2, object.GetCenterPosition()[1]-object.size[1]/2,-mapobjectsizeconstant/2]);
				let resultArray = LineTrace_Sub1(lineeq, areaeq1);
				if (resultArray.length > 0 && resultArray[1] >= object.GetCenterPosition()[1]-object.size[1]/2 && resultArray[1] <= object.GetCenterPosition()[1]+object.size[1]/2) this.collidedobjectsinfo.push([object, resultArray]);
				let areaeq2 = new AreaEquation([object.GetCenterPosition()[0], object.GetCenterPosition()[1]-object.size[1]/2,0], [object.GetCenterPosition()[0]-object.size[0]/2, object.GetCenterPosition()[1]-object.size[1]/2,mapobjectsizeconstant/2],[object.GetCenterPosition()[0]-object.size[0]/2, object.GetCenterPosition()[1]-object.size[1]/2,-mapobjectsizeconstant/2]);
				resultArray = LineTrace_Sub1(lineeq, areaeq2);
				if (resultArray.length > 0 && resultArray[0] >= object.GetCenterPosition()[0]-object.size[0]/2 && resultArray[0] <= object.GetCenterPosition()[0]+object.size[0]/2) this.collidedobjectsinfo.push([object, resultArray]);
				let areaeq3 = new AreaEquation([object.GetCenterPosition()[0]+object.size[0]/2, object.GetCenterPosition()[1],0], [object.GetCenterPosition()[0]+object.size[0]/2, object.GetCenterPosition()[1]+object.size[1]/2,mapobjectsizeconstant/2],[object.GetCenterPosition()[0]+object.size[0]/2, object.GetCenterPosition()[1]+object.size[1]/2,-mapobjectsizeconstant/2]);
				resultArray = LineTrace_Sub1(lineeq, areaeq3);
				if (resultArray.length > 0 && resultArray[1] >= object.GetCenterPosition()[1]-object.size[1]/2 && resultArray[1] <= object.GetCenterPosition()[1]+object.size[1]/2) this.collidedobjectsinfo.push([object, resultArray]);
				let areaeq4 = new AreaEquation([object.GetCenterPosition()[0], object.GetCenterPosition()[1]+object.size[1]/2,0], [object.GetCenterPosition()[0]+object.size[0]/2, object.GetCenterPosition()[1]+object.size[1]/2,mapobjectsizeconstant/2],[object.GetCenterPosition()[0]+object.size[0], object.GetCenterPosition()[1]+object.size[1],-mapobjectsizeconstant/2]);
				resultArray = LineTrace_Sub1(lineeq, areaeq4);
				if (resultArray.length > 0 && resultArray[0] >= object.GetCenterPosition()[0]-object.size[0]/2 && resultArray[0] <= object.GetCenterPosition()[0]+object.size[0]/2) this.collidedobjectsinfo.push([object, resultArray]);
			} else if (object.collidetype === 1){ // cylinder -> only find success/fail
				let cylindereq = new CylinderEquation(object.GetCenterPosition(), object.size);
				let hitpoint = LineTrace_Sub2(lineeq, cylindereq);
				if ((hitpoint[0] - this.startpos[0]) * (hitpoint[0] - this.startpos[0]) + (hitpoint[1] - this.startpos[1]) + (hitpoint[2] - this.startpos[2]) * (hitpoint[2] - this.startpos[2]) < (this.endpos[0] - this.startpos[0]) * (this.endpos[0] - this.startpos[0]) + (this.endpos[1] - this.startpos[1]) * (this.endpos[1] - this.startpos[1]) + (this.endpos[2] - this.startpos[2]) * (this.endpos[2] - this.startpos[2]) ) this.collidedobjectsinfo.push([object, hitpoint]);
			}
		}
	}
	this.GetClosestCollidedPosition = () => { // only find cube collided position;
		let collidedposition = this.endpos;
		for (let objectinfo of this.collidedobjectsinfo) {
			if (objectinfo.length > 1) {
				let line1 = new LineEquation(this.startpos, objectinfo[1]);
				let criterionline = new LineEquation(this.startpos, this.endpos);
				if (m4.normalize(criterionline.linevector)[0] * m4.normalize(line1.linevector)[0] >0 && GetLineLength(this.startpos, objectinfo[1]) <= GetLineLength(this.startpos, collidedposition)) collidedposition = objectinfo[1];
			}
		}
		return collidedposition;
	}
	this.GetClosestCollidedObject = (rayownerid = -1) => { // only find cube collided position;
		let collidedposition = this.endpos;
		let collidedobject = undefined;
		for (let objectinfo of this.collidedobjectsinfo) {
			if (objectinfo[0].constructor === Player && objectinfo[0].playerID === rayownerid) continue;
			if (objectinfo.length > 1) {
				let line1 = new LineEquation(this.startpos, objectinfo[1]);
				let criterionline = new LineEquation(this.startpos, this.endpos);
				if (m4.normalize(criterionline.linevector)[0] * m4.normalize(line1.linevector)[0] >0 && GetLineLength(this.startpos, objectinfo[1]) <= GetLineLength(this.startpos, collidedposition)) {
					collidedposition = objectinfo[1];
					collidedobject = objectinfo[0];
				}
			}
		}
		return collidedobject;
	}
	this.DrawRay = () => {
		this.visible = true;
		setTimeout(this.DrawRay_timeout, 50);
		return;
	}
	this.DrawRay_timeout = () => {
		this.visible = false;
		return;
	}
};
// -----------------------------------------------global data-------------------------------------------
const up = [0, 1, 0];

// player state
let fieldOfViewRadians = degToRad(90);
let heightcount = 0;
// --------------------------------------------global function -----------------------------------------------
String.format = function() {
	// The string containing the format items (e.g. "{0}")
	// will and always has to be the first argument.
	var theString = arguments[0];
	// start with the second argument (i = 1)
	for (var i = 1; i < arguments.length; i++) {
		// "gm" = RegEx options for Global search (more than one instance)
		// and for Multiline search
		var regEx = new RegExp("\\{" + (i - 1) + "\\}", "gm");
		theString = theString.replace(regEx, arguments[i]);
	}
	return theString;
}

function radToDeg(r) {
    return r * 180 / Math.PI;
}

function degToRad(d) {
return d * Math.PI / 180;
}

function LineTrace_Sub1(lineeq, areaeq) {
	if (lineeq.linevector[0] * areaeq.normalvector[0] + lineeq.linevector[1] * areaeq.normalvector[1] === 0) return [];
	let t = -(areaeq.normalvector[0]*(lineeq.point[0]-areaeq.point[0]) + areaeq.normalvector[1]*(lineeq.point[1]-areaeq.point[1]) + areaeq.normalvector[2]*(lineeq.point[2]-areaeq.point[2])) / (areaeq.normalvector[0]*lineeq.linevector[0] + areaeq.normalvector[1]*lineeq.linevector[1] +areaeq.normalvector[2]*lineeq.linevector[2]);
	return [lineeq.linevector[0]*t + lineeq.point[0], lineeq.linevector[1]*t + lineeq.point[1],lineeq.linevector[2]*t + lineeq.point[2]];
}
function LineTrace_Sub2(lineeq, cylindereq) {
	let a = lineeq.linevector[0];
	let b = lineeq.linevector[1];
	let c = cylindereq.centerpos[0] - lineeq.point[0];
	let d = cylindereq.centerpos[1] - lineeq.point[1];
	let t1 = (a*c + b* d + Math.sqrt( (a*c + b*d) * (a*c + b*d) - (a*a + b*b) * (c*c + d* d - cylindereq.radius * cylindereq.radius) )) / (a*a + b*b);
	let t2 = (a*c + b* d - Math.sqrt( (a*c + b*d) * (a*c + b*d) - (a*a + b*b) * (c*c + d* d - cylindereq.radius * cylindereq.radius) )) / (a*a + b*b);
	let dx1 = a * t1;
	let dy1 = b * t1;
	let dx2 = a * t2;
	let dy2 = b * t2;
	return dx1*dx1+ dy1*dy1 < dx2*dx2 + dy2*dy2 ? [dx1 + lineeq.point[0], dy1 + lineeq.point[1], lineeq.linevector[2]* t1 + lineeq.point[2]] : [dx2 + lineeq.point[0], dy2 + lineeq.point[1], lineeq.linevector[2]* t2 + lineeq.point[2]];
}
function GetLineLength(startpos, endpos) {
	return Math.sqrt((endpos[0] - startpos[0])* (endpos[0] - startpos[0]) + (endpos[1] - startpos[1]) * (endpos[1] - startpos[1]) + (endpos[2] - startpos[2]) * (endpos[2] - startpos[2]));
}
function createShader(gl, type, source) {
  var shader = gl.createShader(type);
  gl.shaderSource(shader, source);
  gl.compileShader(shader);
  var success = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
  if (success) {
    return shader;
  }

  console.log(gl.getShaderInfoLog(shader));
  gl.deleteShader(shader);
}

function createProgram(gl, vertexShader, fragmentShader) {
  var program = gl.createProgram();
  gl.attachShader(program, vertexShader);
  gl.attachShader(program, fragmentShader);
  gl.linkProgram(program);
  var success = gl.getProgramParameter(program, gl.LINK_STATUS);
  if (success) {
    return program;
  }

  console.log(gl.getProgramInfoLog(program));
  gl.deleteProgram(program);
}
function updateFieldOfView(event, value) {
    fieldOfViewRadians = degToRad(value);
  }
function GenerateProjectile(pos, size, cameraMatrix) { // pos: [x, y](center), size: integer, cameraMatrix: 4x4 matrix
	return [
		//plane 1
		2*pos[0] +size* m4.getForward(cameraMatrix)[0]+size* m4.getRight(cameraMatrix)[0] + size *m4.getUp(cameraMatrix)[0],
		size* m4.getForward(cameraMatrix)[1]+size* m4.getRight(cameraMatrix)[1] + size *m4.getUp(cameraMatrix)[1],
		2*pos[1] +size* m4.getForward(cameraMatrix)[2]+size* m4.getRight(cameraMatrix)[2] + size *m4.getUp(cameraMatrix)[2],
		2*pos[0] +size* m4.getForward(cameraMatrix)[0]+size* m4.getRight(cameraMatrix)[0] - size *m4.getUp(cameraMatrix)[0],
		size* m4.getForward(cameraMatrix)[1]+size* m4.getRight(cameraMatrix)[1] - size *m4.getUp(cameraMatrix)[1],
		2*pos[1] +size* m4.getForward(cameraMatrix)[2]+size* m4.getRight(cameraMatrix)[2] - size *m4.getUp(cameraMatrix)[2],
		2*pos[0] +size* m4.getForward(cameraMatrix)[0]-size* m4.getRight(cameraMatrix)[0] - size *m4.getUp(cameraMatrix)[0],
		size* m4.getForward(cameraMatrix)[1]-size* m4.getRight(cameraMatrix)[1] - size *m4.getUp(cameraMatrix)[1],
		2*pos[1] +size* m4.getForward(cameraMatrix)[2]-size* m4.getRight(cameraMatrix)[2] - size *m4.getUp(cameraMatrix)[2],
		2*pos[0] +size* m4.getForward(cameraMatrix)[0]+size* m4.getRight(cameraMatrix)[0] + size *m4.getUp(cameraMatrix)[0],
		size* m4.getForward(cameraMatrix)[1]+size* m4.getRight(cameraMatrix)[1] + size *m4.getUp(cameraMatrix)[1],
		2*pos[1] +size* m4.getForward(cameraMatrix)[2]+size* m4.getRight(cameraMatrix)[2] + size *m4.getUp(cameraMatrix)[2],
		2*pos[0] +size* m4.getForward(cameraMatrix)[0]-size* m4.getRight(cameraMatrix)[0] - size *m4.getUp(cameraMatrix)[0],
		size* m4.getForward(cameraMatrix)[1]-size* m4.getRight(cameraMatrix)[1] - size *m4.getUp(cameraMatrix)[1],
		2*pos[1] +size* m4.getForward(cameraMatrix)[2]-size* m4.getRight(cameraMatrix)[2] - size *m4.getUp(cameraMatrix)[2],
		2*pos[0] +size* m4.getForward(cameraMatrix)[0]-size* m4.getRight(cameraMatrix)[0] + size *m4.getUp(cameraMatrix)[0],
		size* m4.getForward(cameraMatrix)[1]-size* m4.getRight(cameraMatrix)[1] + size *m4.getUp(cameraMatrix)[1],
		2*pos[1] +size* m4.getForward(cameraMatrix)[2]-size* m4.getRight(cameraMatrix)[2] + size *m4.getUp(cameraMatrix)[2],
		
		//plane 2
		2*pos[0] +size* m4.getForward(cameraMatrix)[0]-size* m4.getRight(cameraMatrix)[0] + size *m4.getUp(cameraMatrix)[0],
		size* m4.getForward(cameraMatrix)[1]-size* m4.getRight(cameraMatrix)[1] + size *m4.getUp(cameraMatrix)[1],
		2*pos[1] +size* m4.getForward(cameraMatrix)[2]-size* m4.getRight(cameraMatrix)[2] + size *m4.getUp(cameraMatrix)[2],
		2*pos[0] +size* m4.getForward(cameraMatrix)[0]-size* m4.getRight(cameraMatrix)[0] - size *m4.getUp(cameraMatrix)[0],
		size* m4.getForward(cameraMatrix)[1]-size* m4.getRight(cameraMatrix)[1] - size *m4.getUp(cameraMatrix)[1],
		2*pos[1] +size* m4.getForward(cameraMatrix)[2]-size* m4.getRight(cameraMatrix)[2] - size *m4.getUp(cameraMatrix)[2],
		2*pos[0] -size* m4.getForward(cameraMatrix)[0]-size* m4.getRight(cameraMatrix)[0] - size *m4.getUp(cameraMatrix)[0],
		-size* m4.getForward(cameraMatrix)[1]-size* m4.getRight(cameraMatrix)[1] - size *m4.getUp(cameraMatrix)[1],
		2*pos[1] -size* m4.getForward(cameraMatrix)[2]-size* m4.getRight(cameraMatrix)[2] - size *m4.getUp(cameraMatrix)[2],
		2*pos[0] +size* m4.getForward(cameraMatrix)[0]-size* m4.getRight(cameraMatrix)[0] + size *m4.getUp(cameraMatrix)[0],
		size* m4.getForward(cameraMatrix)[1]-size* m4.getRight(cameraMatrix)[1] + size *m4.getUp(cameraMatrix)[1],
		2*pos[1] +size* m4.getForward(cameraMatrix)[2]-size* m4.getRight(cameraMatrix)[2] + size *m4.getUp(cameraMatrix)[2],
		2*pos[0] -size* m4.getForward(cameraMatrix)[0]-size* m4.getRight(cameraMatrix)[0] - size *m4.getUp(cameraMatrix)[0],
		-size* m4.getForward(cameraMatrix)[1]-size* m4.getRight(cameraMatrix)[1] - size *m4.getUp(cameraMatrix)[1],
		2*pos[1] -size* m4.getForward(cameraMatrix)[2]-size* m4.getRight(cameraMatrix)[2] - size *m4.getUp(cameraMatrix)[2],
		2*pos[0] -size* m4.getForward(cameraMatrix)[0]-size* m4.getRight(cameraMatrix)[0] + size *m4.getUp(cameraMatrix)[0],
		-size* m4.getForward(cameraMatrix)[1]-size* m4.getRight(cameraMatrix)[1] + size *m4.getUp(cameraMatrix)[1],
		2*pos[1] -size* m4.getForward(cameraMatrix)[2]-size* m4.getRight(cameraMatrix)[2] + size *m4.getUp(cameraMatrix)[2],
		
		// plane 3
		2*pos[0] -size* m4.getForward(cameraMatrix)[0]-size* m4.getRight(cameraMatrix)[0] + size *m4.getUp(cameraMatrix)[0],
		-size* m4.getForward(cameraMatrix)[1]-size* m4.getRight(cameraMatrix)[1] + size *m4.getUp(cameraMatrix)[1],
		2*pos[1] -size* m4.getForward(cameraMatrix)[2]-size* m4.getRight(cameraMatrix)[2] + size *m4.getUp(cameraMatrix)[2],
		2*pos[0] -size* m4.getForward(cameraMatrix)[0]-size* m4.getRight(cameraMatrix)[0] - size *m4.getUp(cameraMatrix)[0],
		-size* m4.getForward(cameraMatrix)[1]-size* m4.getRight(cameraMatrix)[1] - size *m4.getUp(cameraMatrix)[1],
		2*pos[1] -size* m4.getForward(cameraMatrix)[2]-size* m4.getRight(cameraMatrix)[2] - size *m4.getUp(cameraMatrix)[2],
		2*pos[0] -size* m4.getForward(cameraMatrix)[0]+size* m4.getRight(cameraMatrix)[0] - size *m4.getUp(cameraMatrix)[0],
		-size* m4.getForward(cameraMatrix)[1]+size* m4.getRight(cameraMatrix)[1] - size *m4.getUp(cameraMatrix)[1],
		2*pos[1] -size* m4.getForward(cameraMatrix)[2]+size* m4.getRight(cameraMatrix)[2] - size *m4.getUp(cameraMatrix)[2],
		2*pos[0] -size* m4.getForward(cameraMatrix)[0]-size* m4.getRight(cameraMatrix)[0] + size *m4.getUp(cameraMatrix)[0],
		-size* m4.getForward(cameraMatrix)[1]-size* m4.getRight(cameraMatrix)[1] + size *m4.getUp(cameraMatrix)[1],
		2*pos[1] -size* m4.getForward(cameraMatrix)[2]-size* m4.getRight(cameraMatrix)[2] + size *m4.getUp(cameraMatrix)[2],
		2*pos[0] -size* m4.getForward(cameraMatrix)[0]+size* m4.getRight(cameraMatrix)[0] - size *m4.getUp(cameraMatrix)[0],
		-size* m4.getForward(cameraMatrix)[1]+size* m4.getRight(cameraMatrix)[1] - size *m4.getUp(cameraMatrix)[1],
		2*pos[1] -size* m4.getForward(cameraMatrix)[2]+size* m4.getRight(cameraMatrix)[2] - size *m4.getUp(cameraMatrix)[2],
		2*pos[0] -size* m4.getForward(cameraMatrix)[0]+size* m4.getRight(cameraMatrix)[0] + size *m4.getUp(cameraMatrix)[0],
		-size* m4.getForward(cameraMatrix)[1]+size* m4.getRight(cameraMatrix)[1] + size *m4.getUp(cameraMatrix)[1],
		2*pos[1] -size* m4.getForward(cameraMatrix)[2]+size* m4.getRight(cameraMatrix)[2] + size *m4.getUp(cameraMatrix)[2],
		
		// plane 4
		2*pos[0] -size* m4.getForward(cameraMatrix)[0]+size* m4.getRight(cameraMatrix)[0] + size *m4.getUp(cameraMatrix)[0],
		-size* m4.getForward(cameraMatrix)[1]+size* m4.getRight(cameraMatrix)[1] + size *m4.getUp(cameraMatrix)[1],
		2*pos[1] -size* m4.getForward(cameraMatrix)[2]+size* m4.getRight(cameraMatrix)[2] + size *m4.getUp(cameraMatrix)[2],
		2*pos[0] -size* m4.getForward(cameraMatrix)[0]+size* m4.getRight(cameraMatrix)[0] - size *m4.getUp(cameraMatrix)[0],
		-size* m4.getForward(cameraMatrix)[1]+size* m4.getRight(cameraMatrix)[1] - size *m4.getUp(cameraMatrix)[1],
		2*pos[1] -size* m4.getForward(cameraMatrix)[2]+size* m4.getRight(cameraMatrix)[2] - size *m4.getUp(cameraMatrix)[2],
		2*pos[0] +size* m4.getForward(cameraMatrix)[0]+size* m4.getRight(cameraMatrix)[0] - size *m4.getUp(cameraMatrix)[0],
		size* m4.getForward(cameraMatrix)[1]+size* m4.getRight(cameraMatrix)[1] - size *m4.getUp(cameraMatrix)[1],
		2*pos[1] +size* m4.getForward(cameraMatrix)[2]+size* m4.getRight(cameraMatrix)[2] - size *m4.getUp(cameraMatrix)[2],
		2*pos[0] -size* m4.getForward(cameraMatrix)[0]+size* m4.getRight(cameraMatrix)[0] + size *m4.getUp(cameraMatrix)[0],
		-size* m4.getForward(cameraMatrix)[1]+size* m4.getRight(cameraMatrix)[1] + size *m4.getUp(cameraMatrix)[1],
		2*pos[1] -size* m4.getForward(cameraMatrix)[2]+size* m4.getRight(cameraMatrix)[2] + size *m4.getUp(cameraMatrix)[2],
		2*pos[0] +size* m4.getForward(cameraMatrix)[0]+size* m4.getRight(cameraMatrix)[0] - size *m4.getUp(cameraMatrix)[0],
		size* m4.getForward(cameraMatrix)[1]+size* m4.getRight(cameraMatrix)[1] - size *m4.getUp(cameraMatrix)[1],
		2*pos[1] +size* m4.getForward(cameraMatrix)[2]+size* m4.getRight(cameraMatrix)[2] - size *m4.getUp(cameraMatrix)[2],
		2*pos[0] +size* m4.getForward(cameraMatrix)[0]+size* m4.getRight(cameraMatrix)[0] + size *m4.getUp(cameraMatrix)[0],
		size* m4.getForward(cameraMatrix)[1]+size* m4.getRight(cameraMatrix)[1] + size *m4.getUp(cameraMatrix)[1],
		2*pos[1] +size* m4.getForward(cameraMatrix)[2]+size* m4.getRight(cameraMatrix)[2] + size *m4.getUp(cameraMatrix)[2]
		
	];
}
function GeneratePlaneVertex(pos, size, cameraMatrix) { // pos: [x, y](center), size: integer, height: interger, cameraMatrix: 4x4 matrix
	return [
		//plane
		2*pos[0] +size* m4.getForward(cameraMatrix)[0]+size* m4.getRight(cameraMatrix)[0] + size *m4.getUp(cameraMatrix)[0],
		size* m4.getForward(cameraMatrix)[1]+size* m4.getRight(cameraMatrix)[1] + size *m4.getUp(cameraMatrix)[1],
		2*pos[1] +size* m4.getForward(cameraMatrix)[2]+size* m4.getRight(cameraMatrix)[2] + size *m4.getUp(cameraMatrix)[2],
		2*pos[0] +size* m4.getForward(cameraMatrix)[0]+size* m4.getRight(cameraMatrix)[0] - size *m4.getUp(cameraMatrix)[0],
		size* m4.getForward(cameraMatrix)[1]+size* m4.getRight(cameraMatrix)[1] - size *m4.getUp(cameraMatrix)[1],
		2*pos[1] +size* m4.getForward(cameraMatrix)[2]+size* m4.getRight(cameraMatrix)[2] - size *m4.getUp(cameraMatrix)[2],
		2*pos[0] +size* m4.getForward(cameraMatrix)[0]-size* m4.getRight(cameraMatrix)[0] - size *m4.getUp(cameraMatrix)[0],
		size* m4.getForward(cameraMatrix)[1]-size* m4.getRight(cameraMatrix)[1] - size *m4.getUp(cameraMatrix)[1],
		2*pos[1] +size* m4.getForward(cameraMatrix)[2]-size* m4.getRight(cameraMatrix)[2] - size *m4.getUp(cameraMatrix)[2],
		2*pos[0] +size* m4.getForward(cameraMatrix)[0]+size* m4.getRight(cameraMatrix)[0] + size *m4.getUp(cameraMatrix)[0],
		size* m4.getForward(cameraMatrix)[1]+size* m4.getRight(cameraMatrix)[1] + size *m4.getUp(cameraMatrix)[1],
		2*pos[1] +size* m4.getForward(cameraMatrix)[2]+size* m4.getRight(cameraMatrix)[2] + size *m4.getUp(cameraMatrix)[2],
		2*pos[0] +size* m4.getForward(cameraMatrix)[0]-size* m4.getRight(cameraMatrix)[0] - size *m4.getUp(cameraMatrix)[0],
		size* m4.getForward(cameraMatrix)[1]-size* m4.getRight(cameraMatrix)[1] - size *m4.getUp(cameraMatrix)[1],
		2*pos[1] +size* m4.getForward(cameraMatrix)[2]-size* m4.getRight(cameraMatrix)[2] - size *m4.getUp(cameraMatrix)[2],
		2*pos[0] +size* m4.getForward(cameraMatrix)[0]-size* m4.getRight(cameraMatrix)[0] + size *m4.getUp(cameraMatrix)[0],
		size* m4.getForward(cameraMatrix)[1]-size* m4.getRight(cameraMatrix)[1] + size *m4.getUp(cameraMatrix)[1],
		2*pos[1] +size* m4.getForward(cameraMatrix)[2]-size* m4.getRight(cameraMatrix)[2] + size *m4.getUp(cameraMatrix)[2],
		
		//plane 2
		2*pos[0] +size* m4.getForward(cameraMatrix)[0]-size* m4.getRight(cameraMatrix)[0] + size *m4.getUp(cameraMatrix)[0],
		size* m4.getForward(cameraMatrix)[1]-size* m4.getRight(cameraMatrix)[1] + size *m4.getUp(cameraMatrix)[1],
		2*pos[1] +size* m4.getForward(cameraMatrix)[2]-size* m4.getRight(cameraMatrix)[2] + size *m4.getUp(cameraMatrix)[2],
		2*pos[0] +size* m4.getForward(cameraMatrix)[0]-size* m4.getRight(cameraMatrix)[0] - size *m4.getUp(cameraMatrix)[0],
		size* m4.getForward(cameraMatrix)[1]-size* m4.getRight(cameraMatrix)[1] - size *m4.getUp(cameraMatrix)[1],
		2*pos[1] +size* m4.getForward(cameraMatrix)[2]-size* m4.getRight(cameraMatrix)[2] - size *m4.getUp(cameraMatrix)[2],
		2*pos[0] -size* m4.getForward(cameraMatrix)[0]-size* m4.getRight(cameraMatrix)[0] - size *m4.getUp(cameraMatrix)[0],
		-size* m4.getForward(cameraMatrix)[1]-size* m4.getRight(cameraMatrix)[1] - size *m4.getUp(cameraMatrix)[1],
		2*pos[1] -size* m4.getForward(cameraMatrix)[2]-size* m4.getRight(cameraMatrix)[2] - size *m4.getUp(cameraMatrix)[2],
		2*pos[0] +size* m4.getForward(cameraMatrix)[0]-size* m4.getRight(cameraMatrix)[0] + size *m4.getUp(cameraMatrix)[0],
		size* m4.getForward(cameraMatrix)[1]-size* m4.getRight(cameraMatrix)[1] + size *m4.getUp(cameraMatrix)[1],
		2*pos[1] +size* m4.getForward(cameraMatrix)[2]-size* m4.getRight(cameraMatrix)[2] + size *m4.getUp(cameraMatrix)[2],
		2*pos[0] -size* m4.getForward(cameraMatrix)[0]-size* m4.getRight(cameraMatrix)[0] - size *m4.getUp(cameraMatrix)[0],
		-size* m4.getForward(cameraMatrix)[1]-size* m4.getRight(cameraMatrix)[1] - size *m4.getUp(cameraMatrix)[1],
		2*pos[1] -size* m4.getForward(cameraMatrix)[2]-size* m4.getRight(cameraMatrix)[2] - size *m4.getUp(cameraMatrix)[2],
		2*pos[0] -size* m4.getForward(cameraMatrix)[0]-size* m4.getRight(cameraMatrix)[0] + size *m4.getUp(cameraMatrix)[0],
		-size* m4.getForward(cameraMatrix)[1]-size* m4.getRight(cameraMatrix)[1] + size *m4.getUp(cameraMatrix)[1],
		2*pos[1] -size* m4.getForward(cameraMatrix)[2]-size* m4.getRight(cameraMatrix)[2] + size *m4.getUp(cameraMatrix)[2],
		
		// plane 3
		2*pos[0] -size* m4.getForward(cameraMatrix)[0]-size* m4.getRight(cameraMatrix)[0] + size *m4.getUp(cameraMatrix)[0],
		-size* m4.getForward(cameraMatrix)[1]-size* m4.getRight(cameraMatrix)[1] + size *m4.getUp(cameraMatrix)[1],
		2*pos[1] -size* m4.getForward(cameraMatrix)[2]-size* m4.getRight(cameraMatrix)[2] + size *m4.getUp(cameraMatrix)[2],
		2*pos[0] -size* m4.getForward(cameraMatrix)[0]-size* m4.getRight(cameraMatrix)[0] - size *m4.getUp(cameraMatrix)[0],
		-size* m4.getForward(cameraMatrix)[1]-size* m4.getRight(cameraMatrix)[1] - size *m4.getUp(cameraMatrix)[1],
		2*pos[1] -size* m4.getForward(cameraMatrix)[2]-size* m4.getRight(cameraMatrix)[2] - size *m4.getUp(cameraMatrix)[2],
		2*pos[0] -size* m4.getForward(cameraMatrix)[0]+size* m4.getRight(cameraMatrix)[0] - size *m4.getUp(cameraMatrix)[0],
		-size* m4.getForward(cameraMatrix)[1]+size* m4.getRight(cameraMatrix)[1] - size *m4.getUp(cameraMatrix)[1],
		2*pos[1] -size* m4.getForward(cameraMatrix)[2]+size* m4.getRight(cameraMatrix)[2] - size *m4.getUp(cameraMatrix)[2],
		2*pos[0] -size* m4.getForward(cameraMatrix)[0]-size* m4.getRight(cameraMatrix)[0] + size *m4.getUp(cameraMatrix)[0],
		-size* m4.getForward(cameraMatrix)[1]-size* m4.getRight(cameraMatrix)[1] + size *m4.getUp(cameraMatrix)[1],
		2*pos[1] -size* m4.getForward(cameraMatrix)[2]-size* m4.getRight(cameraMatrix)[2] + size *m4.getUp(cameraMatrix)[2],
		2*pos[0] -size* m4.getForward(cameraMatrix)[0]+size* m4.getRight(cameraMatrix)[0] - size *m4.getUp(cameraMatrix)[0],
		-size* m4.getForward(cameraMatrix)[1]+size* m4.getRight(cameraMatrix)[1] - size *m4.getUp(cameraMatrix)[1],
		2*pos[1] -size* m4.getForward(cameraMatrix)[2]+size* m4.getRight(cameraMatrix)[2] - size *m4.getUp(cameraMatrix)[2],
		2*pos[0] -size* m4.getForward(cameraMatrix)[0]+size* m4.getRight(cameraMatrix)[0] + size *m4.getUp(cameraMatrix)[0],
		-size* m4.getForward(cameraMatrix)[1]+size* m4.getRight(cameraMatrix)[1] + size *m4.getUp(cameraMatrix)[1],
		2*pos[1] -size* m4.getForward(cameraMatrix)[2]+size* m4.getRight(cameraMatrix)[2] + size *m4.getUp(cameraMatrix)[2],
		
		// plane 4
		2*pos[0] -size* m4.getForward(cameraMatrix)[0]+size* m4.getRight(cameraMatrix)[0] + size *m4.getUp(cameraMatrix)[0],
		-size* m4.getForward(cameraMatrix)[1]+size* m4.getRight(cameraMatrix)[1] + size *m4.getUp(cameraMatrix)[1],
		2*pos[1] -size* m4.getForward(cameraMatrix)[2]+size* m4.getRight(cameraMatrix)[2] + size *m4.getUp(cameraMatrix)[2],
		2*pos[0] -size* m4.getForward(cameraMatrix)[0]+size* m4.getRight(cameraMatrix)[0] - size *m4.getUp(cameraMatrix)[0],
		-size* m4.getForward(cameraMatrix)[1]+size* m4.getRight(cameraMatrix)[1] - size *m4.getUp(cameraMatrix)[1],
		2*pos[1] -size* m4.getForward(cameraMatrix)[2]+size* m4.getRight(cameraMatrix)[2] - size *m4.getUp(cameraMatrix)[2],
		2*pos[0] +size* m4.getForward(cameraMatrix)[0]+size* m4.getRight(cameraMatrix)[0] - size *m4.getUp(cameraMatrix)[0],
		size* m4.getForward(cameraMatrix)[1]+size* m4.getRight(cameraMatrix)[1] - size *m4.getUp(cameraMatrix)[1],
		2*pos[1] +size* m4.getForward(cameraMatrix)[2]+size* m4.getRight(cameraMatrix)[2] - size *m4.getUp(cameraMatrix)[2],
		2*pos[0] -size* m4.getForward(cameraMatrix)[0]+size* m4.getRight(cameraMatrix)[0] + size *m4.getUp(cameraMatrix)[0],
		-size* m4.getForward(cameraMatrix)[1]+size* m4.getRight(cameraMatrix)[1] + size *m4.getUp(cameraMatrix)[1],
		2*pos[1] -size* m4.getForward(cameraMatrix)[2]+size* m4.getRight(cameraMatrix)[2] + size *m4.getUp(cameraMatrix)[2],
		2*pos[0] +size* m4.getForward(cameraMatrix)[0]+size* m4.getRight(cameraMatrix)[0] - size *m4.getUp(cameraMatrix)[0],
		size* m4.getForward(cameraMatrix)[1]+size* m4.getRight(cameraMatrix)[1] - size *m4.getUp(cameraMatrix)[1],
		2*pos[1] +size* m4.getForward(cameraMatrix)[2]+size* m4.getRight(cameraMatrix)[2] - size *m4.getUp(cameraMatrix)[2],
		2*pos[0] +size* m4.getForward(cameraMatrix)[0]+size* m4.getRight(cameraMatrix)[0] + size *m4.getUp(cameraMatrix)[0],
		size* m4.getForward(cameraMatrix)[1]+size* m4.getRight(cameraMatrix)[1] + size *m4.getUp(cameraMatrix)[1],
		2*pos[1] +size* m4.getForward(cameraMatrix)[2]+size* m4.getRight(cameraMatrix)[2] + size *m4.getUp(cameraMatrix)[2]
	];
}

// ------------------------------------------------ input control ------------------------------------------------
let keystate = [];
function Input(screen) {
	this.screen = screen;
	this.target;
	this.keyboardinputtimer;
	this.havePointerLock = 'pointerLockElement' in document || 'mozPointerLockElement' in document || 'webkitPointerLockElement' in document;
	this.InitInput = () => {
		if (this.havePointerLock){
			  this.screen.onclick = () => { // requestPointerLock must be in callback
				  this.screen.requestPointerLock = this.screen.requestPointerLock || this.screen.mozRequestPointerLock || this.screen.webkitRequestPointerLock;
				  // Ask the browser to lock the pointer
				  this.screen.requestPointerLock();
			  }
			  // Hook pointer lock state change events
			  
			  document.addEventListener('pointerlockchange', this.changeCallback, false);
			  document.addEventListener('mozpointerlockchange', this.changeCallback, false);
			  document.addEventListener('webkitpointerlockchange', this.changeCallback, false);
			  
			  document.addEventListener('pointerlockerror', this.errorCallback, false);
			  document.addEventListener('mozpointerlockerror', this.errorCallback, false);
			  document.addEventListener('webkitpointerlockerror', this.errorCallback, false);
		}
		return;
	}
	 // ----------------------mouse management----------------------------------
	this.GrabInput = (target) => {
		this.target = target;
		this.keyboardinputtimer = setInterval(this.target.moveSomething, 10);
		return;
	};
	this.manageKeyboardInputDown = () => {
			if (event.keyCode === 65 || event.keyCode === 97) //a
				keystate[0] = true;
			if (event.keyCode === 68 || event.keyCode === 100) //d
				keystate[1] = true;
			if (event.keyCode === 83 || event.keyCode === 115) //s
				keystate[2] = true;
			if (event.keyCode === 87 || event.keyCode === 119) // w
				keystate[3] = true;
			if (event.keyCode === 81 || event.keyCode === 113) // q
				keystate[4] = true;
			if (event.keyCode === 69 || event.keyCode === 101) //e
				keystate[5] = true;
			if (event.keyCode === 82 || event.keyCode === 114) //r
				keystate[6] = true;
			if (event.keyCode === 70 || event.keyCode === 102) // f
				keystate[7] = true;
	  };
	  this.manageKeyboardInputUp = () => {
			if (event.keyCode === 65 || event.keyCode === 97) // a
				keystate[0] = false;
			if (event.keyCode === 68 || event.keyCode === 100) //d
				keystate[1] = false;
			if (event.keyCode === 83 || event.keyCode === 115) //s
				keystate[2] = false;
			if (event.keyCode === 87 || event.keyCode === 119) //w
				keystate[3] = false;
			if (event.keyCode === 81 || event.keyCode === 113) //q
				keystate[4] = false;
			if (event.keyCode === 69 || event.keyCode === 101) //e
				keystate[5] = false;
			if (event.keyCode === 82 || event.keyCode === 114) //r
				keystate[6] = false;
			if (event.keyCode === 70 || event.keyCode === 102) // f
				keystate[7] = false;
	  };
	  this.errorCallback = (e) => {
		  alert( "Fail to initialize point lock process" );
	  }
	  this.moveCallback = (e) => {
		  let movementX = 0;
		  let movementY = 0;
		  movementX = e.movementX ||
			  e.mozMovementX          ||
			  e.webkitMovementX       ||
			  0,
		  movementY = e.movementY ||
			  e.mozMovementY      ||
			  e.webkitMovementY   ||
			  0;
		  if (this.target != undefined) {
			  this.target.direction = this.target.direction + degToRad(movementX);
			  ws.send(JSON.stringify({
				type:5,
				id: this.target.playerID,
				pos: this.target.pos,
				direction: this.target.direction
			  }));
		  }
	  }
	  this.ReleasePlayer = () => {
		clearInterval(this.keyboardinputtimer);
		return;
	  }
	  
	  this.changeCallback = (e) => {
		if (document.pointerLockElement === this.screen ||
		  document.mozPointerLockElement === this.screen ||
		  document.webkitPointerLockElement === this.screen) {
		  // Pointer was just locked
		  // Enable the mousemove listener
		  document.addEventListener("mousemove", this.moveCallback);
		  document.addEventListener("keydown", this.manageKeyboardInputDown);
		  document.addEventListener("keyup", this.manageKeyboardInputUp);
		  document.onmousedown = () => {
			switch(event.button) {
				case 0:
					this.target.FireWeapon();
					break;
				case 2:
					this.target.DoSpecialSkill();
					break;
				default:
					break;
			}
		  }
		  document.onmouseup = () => {
			  if (event.button === 0) this.target.ReleaseFire();
			  return;
		  }
		} else {
		  // Disable the mousemove listener
		  document.removeEventListener("mousemove", this.moveCallback);
		  document.removeEventListener("keydown", this.manageKeyboardInputDown);
		  document.removeEventListener("keyup", this.manageKeyboardInputUp);
		  document.onmousedown = () => {
			return;
		  }
		  document.onmouseup = () => {
			return;
		  }
		}
	  }
	  
}

// ------------------------------------------ Engine Main ----------------------------------------------
let mapdataurl = "http://libertyga.me/index.php?title=%EC%82%AC%EC%9A%A9%EC%9E%90:Senouis/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8/%ED%85%8C%EC%8A%A4%ED%8A%B8%EB%A7%B5&action=raw";

let mapinfo; // map information object
let player;
let gamerule;

function EngineMain() {
  // init player
  player = new Player([0, 0], 8, degToRad(0), 1);
  gamerule = new GameRule(0, 0, 0);
  // ----------------------------Procedure Start--------------------------------
  // Get A WebGL context
  let canvas = document.getElementById("MainCanvas");
  
  let gl = canvas.getContext("webgl");
  if (!gl) {
    return;
  }
  // setup GLSL program
  let vertexshader = createShader(gl, gl.VERTEX_SHADER, document.getElementById("3d-vertex-shader").text);
  let fragmentshader = createShader(gl, gl.FRAGMENT_SHADER, document.getElementById("3d-fragment-shader").text);
  
  let program = createProgram(gl, vertexshader, fragmentshader);
  
  let planevertexshader = createShader(gl, gl.VERTEX_SHADER, document.getElementById("2d-vertex-shader").text);
  let planefragmentshader = createShader(gl, gl.FRAGMENT_SHADER, document.getElementById("2d-fragment-shader").text);
  
  let textureprogram = createProgram(gl, planevertexshader, planefragmentshader);
  
  // load map data
  mapinfo = new MapInfo ("25 45 1\n\
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n\
AFFFFFPFFFFFFFFFFFFAFFFFFFFFFAFFFFFFFFFFFFFFW\n\
AFFFFFPFFFFFFFFFFFFWFFFFFFFFFWFFFFFFFFFFFFFFW\n\
AFFRFFAAAFFFFFFFFFFFFFFFFFFFFFFFFFFFAAAAAFFFW\n\
AFFFFHAFFFFFFFFFFFFWFFFFHFFFFWFFFFFFFFFFWFFFW\n\
AFFFHHAFFFFFFFFWAAAAAAAAAAAAAWFFFFFFFFFFWFFFW\n\
AIIAAAAFFFFFFFFFFFFFFFFFFFFFFWFFFFFFFFFFWFFFW\n\
AFFAFFFFFFFFFFFWFFFAAAAAAAFFFWWWWWWFFFFFWFFFW\n\
AFFAFFFFFFFAAAAWFFFFFFFFFFFFFFFFFFFFFFFFFFFFW\n\
AFFFFFFFFFFFFFFWFFFFFFFFFFFFFFFFFFFFFFFFFFFFW\n\
AFFFFFFFFFFFFFFWWWWWFFFFFWWWFFFFFFAWWWWHFFFFW\n\
WWWWFFFFFFAFFFFFFWFFFFFFFFFWFFFFFFAFFFFFFFFFW\n\
WFFFFFFFFFAFFFFFFFFFFFTFFFFFFFFFFFQFFFFFFFFFW\n\
WFFFFFFFFFQFFFFFFWFFFFFFFFFWFFFFFFQFFFFFFWWWW\n\
WFFFFHWWWWQFFFFFFWWWFFFFFWWWWWFFFFFFFFFFFFFFQ\n\
WFFFFFFFFFFFFFFFFFFFFFFFFFFFFWFFFFFFFFFFFFFFQ\n\
WFFFFFFFFFFFFFFFFFFFFFFFFFFFFWQQQQFFFFFFFQFFQ\n\
WFFFWFFFFFWWWWWWFFFQQQQQQQFFFWFFFFFFFFFFFQFFQ\n\
WFFFWFFFFFFFFFFWFFFFFFFFFFFFFFFFFFFFFFQQQQZZQ\n\
WFFFWFFFFFFFFFFWQQQQQQQQQQQQQWFFFFFFFFQHHFFFQ\n\
WFFFWFFFFFFFFFFWFFFFHFFFFWFFFFFFFFFFFFQHFFFFQ\n\
WFFFQQQQQFFFFFFFFFFFFFFFFFFFFFFFFFFFQQQFFBFFQ\n\
WFFFFFFFFFFFFFFWFFFFFFFFFWFFFFFFFFFFFFCFFFFFQ\n\
WFFFFFFFFFFFFFFQFFFFFFFFFQFFFFFFFFFFFFCFFFFFQ\n\
QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ"); 
  ProcedureAfterMapDataload();
  DoSomethingAfterMapLoad();
  // ----------------------Procedure End--------------------------------------
  //---------------------------------- function used inside the procedure -----------------------------------------
  function ProcedureAfterMapDataload () {
	  
	  // -------------------------- initialize web socket ----------------------------------------
	  ws = new WebSocket("ws://" + ip );
	  ws.addEventListener("error" , function() {
		alert("Failed to connect to server...");
	  })
	  ws.addEventListener("open", function() {
		
	  });
	  ws.addEventListener("message", messageHandler);
	  ws.addEventListener("close", closeHandler);
	  
	  
	  //------------------------ get attribute from 3D Shader program ----------------------------
	  // look up where the vertex, color data needs to go.
	  var positionLocation = gl.getAttribLocation(program, "a_position");
	  let colorLocation = gl.getAttribLocation(program, "a_color");
	
	  // lookup uniforms
	  var matrixLocation = gl.getUniformLocation(program, "u_matrix");
	  
	  //------------------------ get attribute from 2D Shader program ----------------------------
	  // look up where the vertex, color data needs to go.
	  let texpositionLocation = gl.getAttribLocation(textureprogram, "a_position");
	  let texcoordLocation = gl.getAttribLocation(textureprogram, "a_texcoord");
	
	  // lookup uniforms
	  let texmatrixLocation = gl.getUniformLocation(textureprogram, "u_matrix");
	  let textureLocation = gl.getUniformLocation(textureprogram, "u_texture");
	  
	  // ----------------------- Create Buffer ------------------------------
	  let positionBuffer = gl.createBuffer();
	  // Put geometry data into buffer
	  gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
	  setMapGeometry(gl, mapinfo);
	  
	  // Put color data into buffer
	  let colorBuffer = gl.createBuffer();
	  gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
	  setMapColors(gl, mapinfo);
	  
	  // Put coordinate for texture
	  let texcoordBuffer = gl.createBuffer();
	  gl.bindBuffer(gl.ARRAY_BUFFER, texcoordBuffer);
	  let texcoords = new Array(2* 6 * 32* MAX_PROJECTILE_PER_PLAYER);
	  gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(texcoords), gl.STATIC_DRAW);
	  
	  var tex = gl.createTexture();
	  gl.bindTexture(gl.TEXTURE_2D, tex);
	 
	  let img = new Image();
	  img.src = "https://static.miraheze.org/libertygamewiki/7/7e/UF_Rocket_Red.png";
	  img.crossOrigin = "anonymous";
	  img.addEventListener('load', function() {
		gl.bindTexture(gl.TEXTURE_2D, tex);
		gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img);
		gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
		gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
		gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
	  });
	  
	  let redplayertex = gl.createTexture();
	  gl.bindTexture(gl.TEXTURE_2D, redplayertex);
	  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array([255, 0, 0, 255]));
	  let redplayerimg = new Image();
	  redplayerimg.src = "https://static.miraheze.org/libertygamewiki/c/c7/UF_Player_Red.png";
	  redplayerimg.crossOrigin = "anonymous";
	  redplayerimg.addEventListener('load', function() {
		gl.bindTexture(gl.TEXTURE_2D, redplayertex);
		gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, redplayerimg);
		gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
		gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
		gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
	  });
	  
	  let blueplayertex = gl.createTexture();
	  gl.bindTexture(gl.TEXTURE_2D, blueplayertex);
	  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array([0, 0, 255, 255]));
	  let blueplayerimg = new Image();
	  blueplayerimg.src = "https://static.miraheze.org/libertygamewiki/d/d7/UF_Player_Blue.png";
	  blueplayerimg.crossOrigin = "anonymous";
	  blueplayerimg.addEventListener('load', function() {
		gl.bindTexture(gl.TEXTURE_2D, blueplayertex);
		gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, blueplayerimg);
		gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
		gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
		gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
	  });
	   // dead image
	  let redplayerdeadtex = gl.createTexture();
	  gl.bindTexture(gl.TEXTURE_2D, redplayerdeadtex);
	  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array([255, 0, 0, 255]));
	  let redplayerdeadimg = new Image();
	  redplayerdeadimg.src = "https://static.miraheze.org/libertygamewiki/f/f4/UF_Player_Dead_Red.png";
	  redplayerdeadimg.crossOrigin = "anonymous";
	  redplayerdeadimg.addEventListener('load', function() {
		gl.bindTexture(gl.TEXTURE_2D, redplayerdeadtex);
		gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, redplayerdeadimg);
		gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
		gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
		gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
	  });
	  
	  let blueplayerdeadtex = gl.createTexture();
	  gl.bindTexture(gl.TEXTURE_2D, blueplayerdeadtex);
	  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array([0, 0, 255, 255]));
	  let blueplayerdeadimg = new Image();
	  blueplayerdeadimg.crossOrigin = "anonymous";
	  blueplayerdeadimg.src = "https://static.miraheze.org/libertygamewiki/6/6a/UF_Player_Dead_Blue.png";
	  blueplayerdeadimg.addEventListener('load', function() {
		gl.bindTexture(gl.TEXTURE_2D, blueplayerdeadtex);
		gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, blueplayerdeadimg);
		gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
		gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
		gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
	  });
	  
	  let explosiontex = gl.createTexture();
	  gl.bindTexture(gl.TEXTURE_2D, explosiontex);
	  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array([0, 0, 255, 255]));
	  let explosionimg = new Image();
	  explosionimg.src = "https://static.miraheze.org/libertygamewiki/f/f0/UF_Explosion.png";
	  explosionimg.crossOrigin = "anonymous";
	  explosionimg.addEventListener('load', function() {
		gl.bindTexture(gl.TEXTURE_2D, explosiontex);
		gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, explosionimg);
		gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
		gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
		gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
	  });
	  
	  var healthkittex = gl.createTexture();
	  gl.bindTexture(gl.TEXTURE_2D, healthkittex);
	  let healthkitimg = new Image();
	  healthkitimg.src = "https://static.miraheze.org/libertygamewiki/4/46/UF_Healthkit.png";
	  healthkitimg.crossOrigin = "anonymous";
	  healthkitimg.addEventListener('load', function() {
		gl.bindTexture(gl.TEXTURE_2D, healthkittex);
		gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, healthkitimg);
		gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
		gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
		gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
	  });
	  
	  // Draw screen
	  requestAnimationFrame(drawScene);
	  
	  // Draw the scene.
	  function drawScene() {
	
	    // Tell WebGL how to convert from clip space to pixels
	    gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
		
		gl.enable(gl.CULL_FACE);
		
		gl.enable(gl.BLEND);
		
		gl.enable(gl.DEPTH_TEST);
		
		gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
		// Clear the canvas.
	    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
		
	    // Tell it to use our program (pair of shaders)
	    gl.useProgram(program);
	
	    // Turn on the attribute
	    gl.enableVertexAttribArray(positionLocation);
		
		gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
		
	    // Tell the attribute how to get data out of positionBuffer (ARRAY_BUFFER)
	    var size = 3;          // 3 components per iteration
	    var type = gl.FLOAT;   // the data is 32bit floats
	    var normalize = false; // don't normalize the data
	    var stride = 0;        // 0 = move forward size * sizeof(type) each iteration to get the next position
	    var offset = 0;        // start at the beginning of the buffer
	    gl.vertexAttribPointer( positionLocation, size, type, normalize, stride, offset);
	
		// Turn on the color attribute
	    gl.enableVertexAttribArray(colorLocation);
	
		gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
		
	    // Tell the attribute how to get data out of colorBuffer (ARRAY_BUFFER)
	    var size = 3;                 // 3 components per iteration
	    var type = gl.UNSIGNED_BYTE;  // the data is 8bit unsigned values
	    var normalize = true;         // normalize the data (convert from 0-255 to 0-1)
	    var stride = 0;               // 0 = move forward size * sizeof(type) each iteration to get the next position
	    var offset = 0;               // start at the beginning of the buffer
	    gl.vertexAttribPointer(colorLocation, size, type, normalize, stride, offset);
		
	    // Compute the matrix
	    var aspect = gl.canvas.clientWidth / gl.canvas.clientHeight;
	    var zNear = 1;
	    var zFar = 10000;
	    var projectionMatrix = m4.perspective(fieldOfViewRadians, aspect, zNear, zFar);
	    
	    projectionMatrix = m4.xRotate(projectionMatrix, player.rotation[0]);
	    projectionMatrix = m4.yRotate(projectionMatrix, player.rotation[1]);
	    projectionMatrix = m4.zRotate(projectionMatrix, player.rotation[2]);
	    projectionMatrix = m4.scale(projectionMatrix, player.scale[0], player.scale[1], player.scale[2]);
		
		// Compute a matrix for the camera
		player.cameraMatrix = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
	    player.cameraMatrix = m4.yRotation(player.direction);
	    player.cameraMatrix = m4.translate(player.cameraMatrix, -player.GetCenterPosition()[0], player.height, -player.GetCenterPosition()[1]);
	
	    // Compute a view projection matrix
	    var viewProjectionMatrix = m4.multiply(projectionMatrix, player.cameraMatrix);
	
		var matrix = m4.translate(viewProjectionMatrix, -player.GetCenterPosition()[0], player.height, -player.GetCenterPosition()[1]);
	    // Set the matrix.
	    gl.uniformMatrix4fv(matrixLocation, false, matrix);
		// --------------------------------------------------------draw!!!!-------------------------------------------------
		// Draw map objects
		// Bind it to ARRAY_BUFFER (think of it as ARRAY_BUFFER = positionBuffer)
		offset = 0;
	    var count = (2+mapinfo.mapwallcounter) * 6;
		
		gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
		let tempArray = mapinfo.polygons;
		
		let polygonArray = new Float32Array(tempArray);
		gl.bufferSubData(gl.ARRAY_BUFFER, 0, polygonArray);
	    // Bind the color buffer.
		gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
		tempArray = mapinfo.mapColors;
		let mapColorArray = new Uint8Array( tempArray );
		gl.bufferSubData(gl.ARRAY_BUFFER, 0, mapColorArray);
		
	    gl.drawArrays(gl.TRIANGLES, offset, count);
		
		// Draw rays
		for (let playeritem of playerlist) {
			for (let ray of playeritem.raylist) {
				if (playeritem.raylist.indexOf(ray) > 10) continue;
				else if (ray.visible) {
					tempArray = [];
					gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
					tempArray = tempArray.concat([2*ray.startpos[0], ray.startpos[2], 2*ray.startpos[1]]);
					tempArray = tempArray.concat([2*ray.endpos[0], 0, 2*ray.endpos[1]]);
					polygonArray = new Float32Array(tempArray);
					gl.bufferSubData(gl.ARRAY_BUFFER, 0, polygonArray);
					gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
					tempArray =[255, 255, 0, 255, 255, 0];
					mapColorArray = new Uint8Array( tempArray );
					gl.bufferSubData(gl.ARRAY_BUFFER, 0, mapColorArray);
					// we have already set the matrix, so directly draw
					gl.drawArrays(gl.LINES, 0, 2);
				}
			}
		}
		// Draw projectiles
		// Tell WebGL to use our shader program pair
		gl.useProgram(textureprogram);
		gl.enableVertexAttribArray(texpositionLocation);
		gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
		// Tell the attribute how to get data out of positionBuffer (ARRAY_BUFFER)
		var size = 3;          // 3 components per iteration
		var type = gl.FLOAT;   // the data is 32bit floats
		var normalize = false; // don't normalize the data
		var stride = 0;        // 0 = move forward size * sizeof(type) each iteration to get the next position
		var offset = 0;        // start at the current position
		gl.vertexAttribPointer( texpositionLocation, size, type, normalize, stride, offset);
		
		// Setup the attributes to pull data from our buffers
		gl.enableVertexAttribArray(texcoordLocation);
		gl.bindBuffer(gl.ARRAY_BUFFER, texcoordBuffer);
		gl.vertexAttribPointer(texcoordLocation, 2, gl.FLOAT, false, 0, 0);
		
		// fill the polygon buffer
		gl.bindTexture(gl.TEXTURE_2D, tex);
		gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
		tempArray = [];
		count = 0;
		for (let proj of projectilelist) {
			tempArray = tempArray.concat(proj.vertexlist);
			count += 4*6;
		}
		polygonArray = new Float32Array(tempArray);
		gl.bufferSubData(gl.ARRAY_BUFFER, 0, polygonArray);
		// Tell the shader to get the texture from texture unit 0
		gl.bindBuffer(gl.ARRAY_BUFFER, texcoordBuffer);
		tempArray = [];
		for (let proj of projectilelist) {
			tempArray = tempArray.concat([0.5, 0, 0.5, 0.5, 1, 0.5, 0.5, 0, 1, 0.5, 1, 0]);
			tempArray = tempArray.concat([0.5, 0.5, 0.5, 1.0, 1, 1, 0.5, 0.5, 1, 1, 1, 0.5]);
			tempArray = tempArray.concat([0, 0, 0.5, 0, 0, 0.5, 0, 0.5, 0.5, 0, 0.5, 0.5]);
			tempArray = tempArray.concat([0, 0.5, 0, 1, 0.5, 1, 0, 0.5, 0.5, 1, 0.5, 0.5]);
		}
		let texcoordinates = new Float32Array( tempArray );
		gl.bufferSubData(gl.ARRAY_BUFFER, 0, texcoordinates);
		
		// Set the matrix.
		gl.uniformMatrix4fv(texmatrixLocation, false, matrix);
		gl.uniform1i(textureLocation, 0);
		gl.drawArrays(gl.TRIANGLES, 0, count);
		
		// Draw Player
		
		for (let playeritem of playerlist) {
			if (playeritem.playerID === player.playerID) continue;
			tempArray = [];
			count = 4*6;
			// vertex
			if (playeritem.team === 1) {
				if (playeritem.isdead) gl.bindTexture(gl.TEXTURE_2D, redplayerdeadtex);
				else gl.bindTexture(gl.TEXTURE_2D, redplayertex);
			} else {
				if (playeritem.isdead) gl.bindTexture(gl.TEXTURE_2D, blueplayerdeadtex);
				else gl.bindTexture(gl.TEXTURE_2D, blueplayertex);
			}
			gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
			playeritem.vertexlist = GeneratePlaneVertex(playeritem.GetCenterPosition(), 32, m4.lookAt([playeritem.GetCenterPosition()[0], playeritem.height, playeritem.GetCenterPosition()[1]], [player.GetCenterPosition()[0], player.height, player.GetCenterPosition()[1]], up));
			tempArray = tempArray.concat(playeritem.vertexlist);
			polygonArray = new Float32Array(tempArray);
			gl.bufferSubData(gl.ARRAY_BUFFER, 0, polygonArray);
			// texture coordinate
			gl.bindBuffer(gl.ARRAY_BUFFER, texcoordBuffer);
			tempArray = [];
			if (radToDeg(playeritem.direction - player.direction) % 360 >= 315 || ( radToDeg(playeritem.direction - player.direction) % 360 >= -45 && radToDeg(playeritem.direction - player.direction) % 360 < 45 ) || radToDeg(playeritem.direction - player.direction) % 360 < -315 ) {
				tempArray = tempArray.concat([0.5, 0, 0.5, 0.5, 1, 0.5, 0.5, 0, 1, 0.5, 1, 0]);
				tempArray = tempArray.concat([0.5, 0, 0.5, 0.5, 1, 0.5, 0.5, 0, 1, 0.5, 1, 0]);
				tempArray = tempArray.concat([0.5, 0, 0.5, 0.5, 1, 0.5, 0.5, 0, 1, 0.5, 1, 0]);
				tempArray = tempArray.concat([0.5, 0, 0.5, 0.5, 1, 0.5, 0.5, 0, 1, 0.5, 1, 0]);
			} else if ((radToDeg(playeritem.direction - player.direction) % 360 >= 45 && radToDeg(playeritem.direction - player.direction) % 360 < 135) ||(radToDeg(playeritem.direction - player.direction) % 360 < -225 && radToDeg(playeritem.direction - player.direction) % 360 >= -315)) {
				tempArray = tempArray.concat([0, 0.5, 0, 1, 0.5, 1, 0, 0.5, 0.5, 1, 0.5, 0.5]);
				tempArray = tempArray.concat([0, 0.5, 0, 1, 0.5, 1, 0, 0.5, 0.5, 1, 0.5, 0.5]);
				tempArray = tempArray.concat([0, 0.5, 0, 1, 0.5, 1, 0, 0.5, 0.5, 1, 0.5, 0.5]);
				tempArray = tempArray.concat([0, 0.5, 0, 1, 0.5, 1, 0, 0.5, 0.5, 1, 0.5, 0.5]);
			} else if ((radToDeg(playeritem.direction - player.direction) % 360 >= 135 && radToDeg(playeritem.direction - player.direction) % 360 < 225) || (radToDeg(playeritem.direction - player.direction) % 360  < -135 && radToDeg(playeritem.direction - player.direction) % 360 >= -225)) {
				tempArray = tempArray.concat([0, 0, 0, 0.5, 0.5, 0.5, 0, 0, 0.5, 0.5, 0.5, 0]);
				tempArray = tempArray.concat([0, 0, 0, 0.5, 0.5, 0.5, 0, 0, 0.5, 0.5, 0.5, 0]);
				tempArray = tempArray.concat([0, 0, 0, 0.5, 0.5, 0.5, 0, 0, 0.5, 0.5, 0.5, 0]);
				tempArray = tempArray.concat([0, 0, 0, 0.5, 0.5, 0.5, 0, 0, 0.5, 0.5, 0.5, 0]);
			} else {
				tempArray = tempArray.concat([0.5, 0.5, 0.5, 1, 1, 1, 0.5, 0.5, 1, 1, 1, 0.5]);
				tempArray = tempArray.concat([0.5, 0.5, 0.5, 1, 1, 1, 0.5, 0.5, 1, 1, 1, 0.5]);
				tempArray = tempArray.concat([0.5, 0.5, 0.5, 1, 1, 1, 0.5, 0.5, 1, 1, 1, 0.5]);
				tempArray = tempArray.concat([0.5, 0.5, 0.5, 1, 1, 1, 0.5, 0.5, 1, 1, 1, 0.5]);
			}
			texcoordinates = new Float32Array( tempArray );
			gl.bufferSubData(gl.ARRAY_BUFFER, 0, texcoordinates);
			// Set the matrix and draw.
			gl.drawArrays(gl.TRIANGLES, 0, count);
		}
		
		// Draw Healthkit
		gl.bindTexture(gl.TEXTURE_2D, healthkittex);
		gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
		tempArray = [];
		count = 0;
		for (let kit of mapinfo.maphealthkitlist) {
			if (kit.isSpawned) {
				tempArray = tempArray.concat(kit.vertexlist);
				count += 4*6;
			}
		}
		polygonArray = new Float32Array(tempArray);
		gl.bufferSubData(gl.ARRAY_BUFFER, 0, polygonArray);
		// Tell the shader to get the texture from texture unit 0
		gl.bindBuffer(gl.ARRAY_BUFFER, texcoordBuffer);
		tempArray = [];
		for (let kit of mapinfo.maphealthkitlist) {
			if (kit.isSpawned) {
				tempArray = tempArray.concat([0.5, 0, 0.5, 0.5, 1, 0.5, 0.5, 0, 1, 0.5, 1, 0]);
				tempArray = tempArray.concat([0.5, 0.5, 0.5, 1.0, 1, 1, 0.5, 0.5, 1, 1, 1, 0.5]);
				tempArray = tempArray.concat([0, 0, 0, 0.5, 0.5, 0.5, 0, 0, 0.5, 0.5, 0.5, 0]);
				tempArray = tempArray.concat([0, 0.5, 0, 1, 0.5, 1, 0, 0.5, 0.5, 1, 0.5, 0.5]);
			}
		}
		texcoordinates = new Float32Array( tempArray );
		gl.bufferSubData(gl.ARRAY_BUFFER, 0, texcoordinates);
		
		// Set the matrix.
		gl.uniformMatrix4fv(texmatrixLocation, false, matrix);
		gl.uniform1i(textureLocation, 0);
		gl.drawArrays(gl.TRIANGLES, 0, count);
		
		// Draw Explosion
		for (let explosion of explosionlist) {
			if (explosion.active === false) {
				continue;
			}
			tempArray = [];
			count = 4*6;
			gl.bindTexture(gl.TEXTURE_2D, explosiontex);
			// vertex
			gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
			explosion.vertexlist = GeneratePlaneVertex(explosion.GetCenterPosition(), 32, m4.lookAt([explosion.GetCenterPosition()[0], explosion.height, explosion.GetCenterPosition()[1]], [player.GetCenterPosition()[0], player.height, player.GetCenterPosition()[1]], up));
			tempArray = tempArray.concat(explosion.vertexlist);
			polygonArray = new Float32Array(tempArray);
			gl.bufferSubData(gl.ARRAY_BUFFER, 0, polygonArray);
			// texture coordinate
			gl.bindBuffer(gl.ARRAY_BUFFER, texcoordBuffer);
			tempArray = [];
			if ( explosion.counter === 0 ) {
				tempArray = tempArray.concat([0, 0, 0, 1, 0.25, 1, 0, 0, 0.25, 1, 0.25, 0]);
				tempArray = tempArray.concat([0, 0, 0, 1, 0.25, 1, 0, 0, 0.25, 1, 0.25, 0]);
				tempArray = tempArray.concat([0, 0, 0, 1, 0.25, 1, 0, 0, 0.25, 1, 0.25, 0]);
				tempArray = tempArray.concat([0, 0, 0, 1, 0.25, 1, 0, 0, 0.25, 1, 0.25, 0]);
			} else if (explosion.counter === 1) {
				tempArray = tempArray.concat([0.25, 0, 0.25, 1, 0.5, 1, 0.25, 0, 0.5, 1, 0.5, 0]);
				tempArray = tempArray.concat([0.25, 0, 0.25, 1, 0.5, 1, 0.25, 0, 0.5, 1, 0.5, 0]);
				tempArray = tempArray.concat([0.25, 0, 0.25, 1, 0.5, 1, 0.25, 0, 0.5, 1, 0.5, 0]);
				tempArray = tempArray.concat([0.25, 0, 0.25, 1, 0.5, 1, 0.25, 0, 0.5, 1, 0.5, 0]);
			} else if (explosion.counter === 2) {
				tempArray = tempArray.concat([0.5, 0, 0.5, 1, 0.75, 1, 0.5, 0, 0.75, 1, 0.75, 0]);
				tempArray = tempArray.concat([0.5, 0, 0.5, 1, 0.75, 1, 0.5, 0, 0.75, 1, 0.75, 0]);
				tempArray = tempArray.concat([0.5, 0, 0.5, 1, 0.75, 1, 0.5, 0, 0.75, 1, 0.75, 0]);
				tempArray = tempArray.concat([0.5, 0, 0.5, 1, 0.75, 1, 0.5, 0, 0.75, 1, 0.75, 0]);
			} else {
				tempArray = tempArray.concat([0.75, 0, 0.75, 1, 1, 1, 0.75, 0, 1, 1, 1, 0]);
				tempArray = tempArray.concat([0.75, 0, 0.75, 1, 1, 1, 0.75, 0, 1, 1, 1, 0]);
				tempArray = tempArray.concat([0.75, 0, 0.75, 1, 1, 1, 0.75, 0, 1, 1, 1, 0]);
				tempArray = tempArray.concat([0.75, 0, 0.75, 1, 1, 1, 0.75, 0, 1, 1, 1, 0]);
				explosion.active = false;
			}
			explosion.counter += 1;
			texcoordinates = new Float32Array( tempArray );
			gl.bufferSubData(gl.ARRAY_BUFFER, 0, texcoordinates);
			// Set the matrix and draw.
			gl.drawArrays(gl.TRIANGLES, 0, count);
		}
		for (let explosion of explosionlist) {
			if (explosion.active === false) explosionlist.splice(explosionlist.indexOf(explosion), 1);
		}
		// draw ui
		DrawUI();
		
		requestAnimationFrame(drawScene);
	  }
  }
  // ---------End----------
}
// ---------------------------------Matrix control -------------------------------
var m4 = {
  orthographic: function(left, right, bottom, top, near, far) {
    return [
      2 / (right - left), 0, 0, 0,
      0, 2 / (top - bottom), 0, 0,
      0, 0, 2 / (near - far), 0,
 
      (left + right) / (left - right),
      (bottom + top) / (bottom - top),
      (near + far) / (near - far),
      1,
    ];
  },
  perspective: function(fieldOfViewInRadians, aspect, near, far) {
    var f = Math.tan(Math.PI * 0.5 - 0.5 * fieldOfViewInRadians);
    var rangeInv = 1.0 / (near - far);

    return [
      f / aspect, 0, 0, 0,
      0, f, 0, 0,
      0, 0, (near + far) * rangeInv, -1,
      0, 0, near * far * rangeInv * 2, 0
    ];
  },

  projection: function(width, height, depth) {
    // Note: This matrix flips the Y axis so 0 is at the top.
    return [
       2 / width, 0, 0, 0,
       0, -2 / height, 0, 0,
       0, 0, 2 / depth, 0,
      -1, 1, 0, 1,
    ];
  },

  multiply: function(a, b) {
    var a00 = a[0 * 4 + 0];
    var a01 = a[0 * 4 + 1];
    var a02 = a[0 * 4 + 2];
    var a03 = a[0 * 4 + 3];
    var a10 = a[1 * 4 + 0];
    var a11 = a[1 * 4 + 1];
    var a12 = a[1 * 4 + 2];
    var a13 = a[1 * 4 + 3];
    var a20 = a[2 * 4 + 0];
    var a21 = a[2 * 4 + 1];
    var a22 = a[2 * 4 + 2];
    var a23 = a[2 * 4 + 3];
    var a30 = a[3 * 4 + 0];
    var a31 = a[3 * 4 + 1];
    var a32 = a[3 * 4 + 2];
    var a33 = a[3 * 4 + 3];
    var b00 = b[0 * 4 + 0];
    var b01 = b[0 * 4 + 1];
    var b02 = b[0 * 4 + 2];
    var b03 = b[0 * 4 + 3];
    var b10 = b[1 * 4 + 0];
    var b11 = b[1 * 4 + 1];
    var b12 = b[1 * 4 + 2];
    var b13 = b[1 * 4 + 3];
    var b20 = b[2 * 4 + 0];
    var b21 = b[2 * 4 + 1];
    var b22 = b[2 * 4 + 2];
    var b23 = b[2 * 4 + 3];
    var b30 = b[3 * 4 + 0];
    var b31 = b[3 * 4 + 1];
    var b32 = b[3 * 4 + 2];
    var b33 = b[3 * 4 + 3];
    return [
      b00 * a00 + b01 * a10 + b02 * a20 + b03 * a30,
      b00 * a01 + b01 * a11 + b02 * a21 + b03 * a31,
      b00 * a02 + b01 * a12 + b02 * a22 + b03 * a32,
      b00 * a03 + b01 * a13 + b02 * a23 + b03 * a33,
      b10 * a00 + b11 * a10 + b12 * a20 + b13 * a30,
      b10 * a01 + b11 * a11 + b12 * a21 + b13 * a31,
      b10 * a02 + b11 * a12 + b12 * a22 + b13 * a32,
      b10 * a03 + b11 * a13 + b12 * a23 + b13 * a33,
      b20 * a00 + b21 * a10 + b22 * a20 + b23 * a30,
      b20 * a01 + b21 * a11 + b22 * a21 + b23 * a31,
      b20 * a02 + b21 * a12 + b22 * a22 + b23 * a32,
      b20 * a03 + b21 * a13 + b22 * a23 + b23 * a33,
      b30 * a00 + b31 * a10 + b32 * a20 + b33 * a30,
      b30 * a01 + b31 * a11 + b32 * a21 + b33 * a31,
      b30 * a02 + b31 * a12 + b32 * a22 + b33 * a32,
      b30 * a03 + b31 * a13 + b32 * a23 + b33 * a33,
    ];
  },

  translation: function(tx, ty, tz) {
    return [
       1,  0,  0,  0,
       0,  1,  0,  0,
       0,  0,  1,  0,
       tx, ty, tz, 1,
    ];
  },

  xRotation: function(angleInRadians) {
    var c = Math.cos(angleInRadians);
    var s = Math.sin(angleInRadians);

    return [
      1, 0, 0, 0,
      0, c, s, 0,
      0, -s, c, 0,
      0, 0, 0, 1,
    ];
  },

  yRotation: function(angleInRadians) {
    var c = Math.cos(angleInRadians);
    var s = Math.sin(angleInRadians);

    return [
      c, 0, -s, 0,
      0, 1, 0, 0,
      s, 0, c, 0,
      0, 0, 0, 1,
    ];
  },

  zRotation: function(angleInRadians) {
    var c = Math.cos(angleInRadians);
    var s = Math.sin(angleInRadians);

    return [
       c, s, 0, 0,
      -s, c, 0, 0,
       0, 0, 1, 0,
       0, 0, 0, 1,
    ];
  },

  scaling: function(sx, sy, sz) {
    return [
      sx, 0,  0,  0,
      0, sy,  0,  0,
      0,  0, sz,  0,
      0,  0,  0,  1,
    ];
  },
  translate: function(m, tx, ty, tz) {
    return m4.multiply(m, m4.translation(tx, ty, tz));
  },

  xRotate: function(m, angleInRadians) {
    return m4.multiply(m, m4.xRotation(angleInRadians));
  },

  yRotate: function(m, angleInRadians) {
    return m4.multiply(m, m4.yRotation(angleInRadians));
  },

  zRotate: function(m, angleInRadians) {
    return m4.multiply(m, m4.zRotation(angleInRadians));
  },

  scale: function(m, sx, sy, sz) {
    return m4.multiply(m, m4.scaling(sx, sy, sz));
  },
  inverse: function(m) {
    var m00 = m[0 * 4 + 0];
    var m01 = m[0 * 4 + 1];
    var m02 = m[0 * 4 + 2];
    var m03 = m[0 * 4 + 3];
    var m10 = m[1 * 4 + 0];
    var m11 = m[1 * 4 + 1];
    var m12 = m[1 * 4 + 2];
    var m13 = m[1 * 4 + 3];
    var m20 = m[2 * 4 + 0];
    var m21 = m[2 * 4 + 1];
    var m22 = m[2 * 4 + 2];
    var m23 = m[2 * 4 + 3];
    var m30 = m[3 * 4 + 0];
    var m31 = m[3 * 4 + 1];
    var m32 = m[3 * 4 + 2];
    var m33 = m[3 * 4 + 3];
    var tmp_0  = m22 * m33;
    var tmp_1  = m32 * m23;
    var tmp_2  = m12 * m33;
    var tmp_3  = m32 * m13;
    var tmp_4  = m12 * m23;
    var tmp_5  = m22 * m13;
    var tmp_6  = m02 * m33;
    var tmp_7  = m32 * m03;
    var tmp_8  = m02 * m23;
    var tmp_9  = m22 * m03;
    var tmp_10 = m02 * m13;
    var tmp_11 = m12 * m03;
    var tmp_12 = m20 * m31;
    var tmp_13 = m30 * m21;
    var tmp_14 = m10 * m31;
    var tmp_15 = m30 * m11;
    var tmp_16 = m10 * m21;
    var tmp_17 = m20 * m11;
    var tmp_18 = m00 * m31;
    var tmp_19 = m30 * m01;
    var tmp_20 = m00 * m21;
    var tmp_21 = m20 * m01;
    var tmp_22 = m00 * m11;
    var tmp_23 = m10 * m01;

    var t0 = (tmp_0 * m11 + tmp_3 * m21 + tmp_4 * m31) -
        (tmp_1 * m11 + tmp_2 * m21 + tmp_5 * m31);
    var t1 = (tmp_1 * m01 + tmp_6 * m21 + tmp_9 * m31) -
        (tmp_0 * m01 + tmp_7 * m21 + tmp_8 * m31);
    var t2 = (tmp_2 * m01 + tmp_7 * m11 + tmp_10 * m31) -
        (tmp_3 * m01 + tmp_6 * m11 + tmp_11 * m31);
    var t3 = (tmp_5 * m01 + tmp_8 * m11 + tmp_11 * m21) -
        (tmp_4 * m01 + tmp_9 * m11 + tmp_10 * m21);

    var d = 1.0 / (m00 * t0 + m10 * t1 + m20 * t2 + m30 * t3);

    return [
      d * t0,
      d * t1,
      d * t2,
      d * t3,
      d * ((tmp_1 * m10 + tmp_2 * m20 + tmp_5 * m30) -
            (tmp_0 * m10 + tmp_3 * m20 + tmp_4 * m30)),
      d * ((tmp_0 * m00 + tmp_7 * m20 + tmp_8 * m30) -
            (tmp_1 * m00 + tmp_6 * m20 + tmp_9 * m30)),
      d * ((tmp_3 * m00 + tmp_6 * m10 + tmp_11 * m30) -
            (tmp_2 * m00 + tmp_7 * m10 + tmp_10 * m30)),
      d * ((tmp_4 * m00 + tmp_9 * m10 + tmp_10 * m20) -
            (tmp_5 * m00 + tmp_8 * m10 + tmp_11 * m20)),
      d * ((tmp_12 * m13 + tmp_15 * m23 + tmp_16 * m33) -
            (tmp_13 * m13 + tmp_14 * m23 + tmp_17 * m33)),
      d * ((tmp_13 * m03 + tmp_18 * m23 + tmp_21 * m33) -
            (tmp_12 * m03 + tmp_19 * m23 + tmp_20 * m33)),
      d * ((tmp_14 * m03 + tmp_19 * m13 + tmp_22 * m33) -
            (tmp_15 * m03 + tmp_18 * m13 + tmp_23 * m33)),
      d * ((tmp_17 * m03 + tmp_20 * m13 + tmp_23 * m23) -
            (tmp_16 * m03 + tmp_21 * m13 + tmp_22 * m23)),
      d * ((tmp_14 * m22 + tmp_17 * m32 + tmp_13 * m12) -
            (tmp_16 * m32 + tmp_12 * m12 + tmp_15 * m22)),
      d * ((tmp_20 * m32 + tmp_12 * m02 + tmp_19 * m22) -
            (tmp_18 * m22 + tmp_21 * m32 + tmp_13 * m02)),
      d * ((tmp_18 * m12 + tmp_23 * m32 + tmp_15 * m02) -
            (tmp_22 * m32 + tmp_14 * m02 + tmp_19 * m12)),
      d * ((tmp_22 * m22 + tmp_16 * m02 + tmp_21 * m12) -
            (tmp_20 * m12 + tmp_23 * m22 + tmp_17 * m02))
    ];
  },
  vectorMultiply: function(v, m) {
    var dst = [];
    for (var i = 0; i < 4; ++i) {
      dst[i] = 0.0;
      for (var j = 0; j < 4; ++j) {
        dst[i] += v[j] * m[j * 4 + i];
      }
    }
    return dst;
  },
  getRight: function (m) {
	return [m[8], m[9], m[10], 0];
  },
  getForward: function(m) {
	return [m[0], m[1], m[2], 0];
  },
  getUp: function (m) {
	return [m[4], m[5], m[6], 0];
  },
  lookAt: function(cameraPosition, target, up) { // all of the parameters is vector
    var zAxis = this.normalize( this.subtractVectors(cameraPosition, target));
    var xAxis = this.normalize(this.cross(up, zAxis));
    var yAxis = this.normalize(this.cross(zAxis, xAxis));
 
    return [
       xAxis[0], xAxis[1], xAxis[2], 0,
       yAxis[0], yAxis[1], yAxis[2], 0,
       zAxis[0], zAxis[1], zAxis[2], 0,
       cameraPosition[0],
       cameraPosition[1],
       cameraPosition[2],
       1,
    ];
  },
  cross: function (a, b) {
	return [a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0]];
  },
  subtractVectors: function (a, b) {
	return [a[0] - b[0], a[1] - b[1], a[2] - b[2]];
  },
  normalize: function (v) {
	  var length = Math.sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
	  // make sure we don't divide by 0.
	  if (length > 0.00001) {
		return [v[0] / length, v[1] / length, v[2] / length];
	  } else {
		return [0, 0, 0];
	  }
  },
};

// Fill the buffer with the values of "W" and "F".
function setMapGeometry(gl, mapInfo) {
  let temparray = mapInfo.polygons.concat( new Array(6* MAX_RAY_NUM)); // for ray
  temparray = temparray.concat (new Array(3* 6 * 4 * MAX_PROJECTILE_NUMBER )); // for projectile
  temparray = temparray.concat (new Array(3*6*32)); // for player
  temparray = temparray.concat(new Array(3* 6 * MAX_PROJECTILE_NUMBER )); // for explosion
  let polygonArray = new Float32Array(temparray);
  gl.bufferData(
      gl.ARRAY_BUFFER,
      polygonArray,
      gl.STATIC_DRAW);
  return;
}

function setMapColors(gl, mapInfo) {
  for (let object of mapInfo.mapobjectlist){
	  if (object.constructor === Door) {
		  if (object.team === 1) {
				mapInfo.mapColors = mapInfo.mapColors.concat([ 
				146, 25, 14,
				146, 25, 14,
				146, 25, 14,
				146, 25, 14,
				146, 25, 14,
				146, 25, 14,
				//wall 2
				146, 25, 14,
				146, 25, 14,
				146, 25, 14,
				146, 25, 14,
				146, 25, 14,
				146, 25, 14
				]);
		  } else if (object.team === 2) {
			    mapInfo.mapColors = mapInfo.mapColors.concat([ 
				50, 14, 146,
				50, 14, 146,
				50, 14, 146,
				50, 14, 146,
				50, 14, 146,
				50, 14, 146,
				//wall 2
				50, 14, 146,
				50, 14, 146,
				50, 14, 146,
				50, 14, 146,
				50, 14, 146,
				50, 14, 146
				]);
		  } else {
			    mapInfo.mapColors = mapInfo.mapColors.concat([ 
				146, 125, 14,
				146, 125, 14,
				146, 125, 14,
				146, 125, 14,
				146, 125, 14,
				146, 125, 14,
				//wall 2
				146, 125, 14,
				146, 125, 14,
				146, 125, 14,
				146, 125, 14,
				146, 125, 14,
				146, 125, 14
				]);
		  }
	  } else if (object.constructor === GameObject) {
		if (object.flag === 0) {
			mapInfo.mapColors = mapInfo.mapColors.concat([ 
			50, 146, 14,
			50, 146, 14,
			50, 146, 14,
			50, 146, 14,
			50, 146, 14,
			50, 146, 14,
			//wall 2
			50, 146, 14,
			50, 146, 14,
			50, 146, 14,
			50, 146, 14,
			50, 146, 14,
			50, 146, 14,
			//wall 3
			50, 146, 14,
			50, 146, 14,
			50, 146, 14,
			50, 146, 14,
			50, 146, 14,
			50, 146, 14,
			//wall 4
			50, 146, 14,
			50, 146, 14,
			50, 146, 14,
			50, 146, 14,
			50, 146, 14,
			50, 146, 14
			]);
		} else if (object.flag === 2) {
			mapInfo.mapColors = mapInfo.mapColors.concat([ 
			50, 14, 146,
			50, 14, 146,
			50, 14, 146,
			50, 14, 146,
			50, 14, 146,
			50, 14, 146,
			//wall 2
			50, 14, 146,
			50, 14, 146,
			50, 14, 146,
			50, 14, 146,
			50, 14, 146,
			50, 14, 146,
			//wall 3
			50, 14, 146,
			50, 14, 146,
			50, 14, 146,
			50, 14, 146,
			50, 14, 146,
			50, 14, 146,
			//wall 4
			50, 14, 146,
			50, 14, 146,
			50, 14, 146,
			50, 14, 146,
			50, 14, 146,
			50, 14, 146
			]);
		} else if (object.flag === 1) {
			mapInfo.mapColors = mapInfo.mapColors.concat([ 
			146, 25, 14,
			146, 25, 14,
			146, 25, 14,
			146, 25, 14,
			146, 25, 14,
			146, 25, 14,
			//wall 2
			146, 25, 14,
			146, 25, 14,
			146, 25, 14,
			146, 25, 14,
			146, 25, 14,
			146, 25, 14,
			//wall 3
			146, 25, 14,
			146, 25, 14,
			146, 25, 14,
			146, 25, 14,
			146, 25, 14,
			146, 25, 14,
			//wall 4
			146, 25, 14,
			146, 25, 14,
			146, 25, 14,
			146, 25, 14,
			146, 25, 14,
			146, 25, 14
			]);
		}
	  }
  }
  let temparray = mapInfo.mapColors.concat(new Array(2*3* MAX_RAY_NUM));
  temparray = temparray.concat (new Array(3* 6 * 4 * MAX_PROJECTILE_NUMBER )); // for projectile
  temparray = temparray.concat (new Array(3*6*32)); // for player
  temparray = temparray.concat(new Array(3* 6 * MAX_PROJECTILE_NUMBER )); // for explosion
  let mapColorArray = new Uint8Array(temparray);
  gl.bufferData(gl.ARRAY_BUFFER, mapColorArray, gl.STATIC_DRAW);
  return;
}

// ---------------------------------------HTML document managing function-------------------------------------
let ip = "";
let playername = "";
let ws;
let killloglist = [];

function killlog_Timeout() {
	if (killloglist.length > 0) {
		killloglist.splice(0, 1);
	}
	return;
}

function DoInitialJob () {
	createCanvasAndShader ();
	EngineMain();
}

function closeHandler() {
	alert(serverclosereason);
}

///////////////////////////////////////////////////////////////////////////////////////////////
// ---------------------------------Client-side message----------------------------------------
// --------------------------------------------------------------------------------------------
// -------------------------------type of receiving message------------------------------------
// 0: list of players (has heavy net load, do not use this frequently)
// 1: connection notice
// 2: disconnection notice
// 3: connection rejected(due to server player number limit or else)
// 4: reserved for chat
// 5: player's current status renewal
// 6: received fired ray
// 7: received fired projectilelist
// 8: initial player information
// 9: reserved for game objective(GameRule related)
// 10: kill log event
// 11: damaging event
// 12: explosion event
// 13: reserved for list of building
// 14: map version request
// 15: player name change event
// 16: reply to teammate number request
// 17: Healthkit touch event
// 18: sound play request
// 19: sound stop request
// 20: respawn event
// 21: scriptversion request
// 22: weapon change notice
// --------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------
// -------------------------------type of sending message--------------------------------------
// 0: request for all player's status
// 1: map version
// 2: player name set request
// 3: class change request
// 4: reserved for chat
// 5: player current position, looking direction info
// 6: fired ray info
// 7: fired projectile info
// 8: reserved for all building's current status
// 9: reserved for building repair
// 10: reserved for building destruction
// 11: heal event request
// 12: teammate number request
// 13: reload request
// 14: script version
// 15: Special skill request(include building construction, zoom in, etc.)
// 16: Weapon change request
// --------------------------------------------------------------------------------------------

let serverclosereason = "서버로부터 연결이 끊겼습니다";


function messageHandler(message) {
	let messageinfo = JSON.parse(message.data);
	switch (messageinfo.type) {
		case 0:
			playerlist = [];
			for (let playeritem of messageinfo.playerlist){
				playerlist.push(new Player(playeritem.pos, 12, playeritem.direction, playeritem.team, playeritem.health, playeritem.id, playeritem.isdead, playeritem.playername, playeritem.classnumber));
			}
			break;
		case 1:
			if (player.playerID != messageinfo.id) { // other player is connected
				playerlist.push(new Player(messageinfo.pos, 12, messageinfo.direction, messageinfo.team, messageinfo.health, messageinfo.id));
			} else { // ok, this is same with my player information, I have to set a reference of player variable to specific element of playerlist
				playerlist[messageinfo.id] = player;
			}
			if (messageinfo.team === 1) {
				redteamnum += 1;
			}
			else if (messageinfo.team  === 2) {
				blueteamnum += 1;
			}
			break;
		case 2:
			var index = messageinfo.id;
			let teamnumber = playerlist[index].team;
			playerlist.splice(index, 1);
			if (teamnumber === 1) {
				redteamnum -= 1;
			}
			else if (teamnumber === 2) {
				blueteamnum -= 1;
			}
			//arrange the new playerlist
			for (let i in playerlist) {
				playerlist[i].PlayerID = i;
			}
			break;
		case 3:
			serverclosereason = messageinfo.message;
			ws.close();
			break;
		case 5:
			if (messageinfo.id === player.playerID){
				player.pos = messageinfo.pos;
				player.direction = messageinfo.direction;
				player.team = messageinfo.team;
				player.healthpoint = messageinfo.health;
				player.canbedamaged = messageinfo.canbedamaged;
				player.classnumber = messageinfo.classnum;
				player.isdead = messageinfo.isdead;
			}
			playerlist[messageinfo.id].pos = messageinfo.pos;
			playerlist[messageinfo.id].direction = messageinfo.direction;
			playerlist[messageinfo.id].team = messageinfo.team;
			playerlist[messageinfo.id].healthpoint = messageinfo.health;
			playerlist[messageinfo.id].canbedamaged = messageinfo.canbedamaged;
			playerlist[messageinfo.id].classnumber = messageinfo.classnum;
			playerlist[messageinfo.id].isdead = messageinfo.isdead;
			break;
		case 6:
			playerlist[messageinfo.id].raylist = [];
			for (let rayinfo of messageinfo.raylist) {
				playerlist[messageinfo.id].raylist.push(new Ray(rayinfo.startpos, rayinfo.endpos));
			}
			for (let ray of playerlist[messageinfo.id].raylist){
				ray.DrawRay();
			}
			break;
		case 7:
			projectilelist = [];
			for (let projectile of messageinfo.projectilelist) {
				switch (projectile.type) {
					case 0:
						projectilelist.push(new Projectile_Rocket (projectile.pos, 8, projectile.direction, projectile.team, playerlist[projectile.shooterid], "http://libertyga.me/images/4/46/UF_Healthkit.png", projectile.type));
						break;
					default:
						break;
				}
			}
			break;
		case 8:
			player = new Player(messageinfo.pos, 12, messageinfo.direction, messageinfo.team, messageinfo.health, messageinfo.id, true, playername, 0);
			player.canbedamaged = messageinfo.canbedamaged;
			player.classnumber = messageinfo.classnum;
			player.isdead = messageinfo.isdead;
			ws.send(JSON.stringify({
				type: 2,
				id: messageinfo.id,
				newname: playername
			}));
			break;
		case 9:
			// reserved for gamerule control
			break;
		case 10:
			let killtext = playerlist[messageinfo.attackerID].playername + " killed " + playerlist[messageinfo.victimID].playername + " with ";
			switch (messageinfo.killtype) {
				case -1: // suicide
					killtext = playerlist[messageinfo.attackerID].playername + " suicided";
					break;
				case 0: // killed by pistol
					killtext = killtext + "pistol";
					break;
				case 1: // reserved for nail gun
					break;
				case 2: // reserved for short shotgun
					break;
				case 3: // reserved
					break;
				case 4: // killed by power shotgun
					killtext = killtext + "power shotgun";
					break;
				case 5: // killed by minigun
					killtext = killtext + "minigun";
					break;
				case 6: // killed by rocket launcher explosion
					killtext = killtext + "rocket launcher";
					break;
				default:
					killtext = playerlist[messageinfo.attackerID].playername + " killed " + playerlist[messageinfo.victimID].playername;
					console.log("unknown type kill event" + messageinfo.killtype);
					break;
			}
			if (killloglist.length >= 10) {
				killloglist.splice(0, 1);
			}
			killloglist.push(killtext);
			setTimeout(killlog_Timeout, 4000);
			break;
		case 11: // damaging event
			if (player.playerID === messageinfo.victimID){
				player.healthpoint -= messageinfo.damage;
				player.isdead = messageinfo.isdead;
				if (messageinfo.isdead) { // if player is dead
					player.healthpoint = 0;
					inputhandler.ReleasePlayer();
					player.ReloadWeapon = () => {
						return;
					};
					player.FireWeapon = () =>{
						return;
					};
					player.DoSpecialSkill = () => {
						return;
					};
					player.ReleaseFire = () => {
						return;
					};
					clearTimeout(player.deadtimer);
					player.deadtimer = setTimeout(deadStateHandler, 4000);
				}
			} else {
				playerlist[messageinfo.victimID].healthpoint -= messageinfo.damage;
				playerlist[messageinfo.victimID].isdead = messageinfo.isdead;
				if (messageinfo.isdead) {
					playerlist[messageinfo.victimID].healthpoint = 0;
				}
			}
			break;
		case 12: // reserved for explosion draw
			// explosiontype 0: damaging explosion, 1:healing explosion
			explosionlist.push(new Explosion(messageinfo.pos, messageinfo.radius, messageinfo.explosiontype));
			break;
		case 13: // reserved for the list of buildings
			break;
		case 14:
			ws.send(JSON.stringify({type:1, id:player.playerID, mapversion:mapinfo.mapversion}));
			break;
		case 15:
			playerlist[messageinfo.id].playername = messageinfo.newname;
			console.log("client "+ messageinfo.id +" changed name to "+ messageinfo.newname);
			break;
		case 16:
			redteamnum = messageinfo.redteamnum;
			blueteamnum = messageinfo.blueteamnum;
			break;
		case 17:
			if (messageinfo.id === player.playerID) {
				player.healthpoint = player.maxhealthpoint;
			}
			mapinfo.maphealthkitlist[messageinfo.healthkitid].isSpawned = messageinfo.isSpawned;
			break;
		case 18: // soundplay start
			break;
		case 19: // soundplay stop
			break;
		case 20: // respawn
			if (player.playerID === messageinfo.id) {
				player.pos = messageinfo.respawnpos;
				player.isdead = false;
			} else {
				playerlist[messageinfo.id].pos = messageinfo.respawnpos;
				playerlist[messageinfo.id].isdead = false;
			}
			break;
		case 21:
			ws.send(JSON.stringify({ type: 14, id: player.playerID, version: scriptversion}));
			break;
		case 22:
			if (player.playerID != messageinfo.id) {
				playerlist[messageinfo.id].currentweapon = messageinfo.currentweapon;
			}
			break;
		default:
			console.log("received message type "+ messageinfo.type);
			break;
	}
}

function deadStateHandler() {
	player.isdead = false;
	player.healthpoint = player.maxhealthpoint;
	inputhandler.GrabInput(player);
	player.ReloadWeapon = () => {
		if (player.currentweapon === 0) {
			player.secondweapon.ReloadWeapon();
		} else {
			player.firstweapon.ReloadWeapon();
		}
	};
	player.FireWeapon = () =>{
		if (player.currentweapon === 0) {
			player.secondweapon.FireWeapon();
		} else {
			player.firstweapon.FireWeapon();
		}
	};
	player.DoSpecialSkill = () => {
		if (player.currentweapon === 0) {
			player.secondweapon.DoSpecialSkill();
		} else {
			player.firstweapon.DoSpecialSkill();
		}
	};
	player.ReleaseFire = () => {
		if (player.currentweapon === 0) {
			player.secondweapon.ReleaseFire();
		} else {
			player.firstweapon.ReleaseFire();
		}
	};
	if (player.team === 1) {
		player.pos = [mapinfo.RedSpawn[0] + 4 , mapinfo.RedSpawn[1] + 4 ];
	} else {
		player.pos = [mapinfo.BlueSpawn[0] + 4 , mapinfo.BlueSpawn[1] + 4 ];
	}
}

function createIPInputBox () {
	let gamedisplay = document.getElementById("mw-content-text");
	gamedisplay.style.height = "1080px";
	let paragraph = document.createElement("p");
	paragraph.setAttribute("id", "infoparagraph");
	paragraph.innerHTML = "IP주소와 포트를 쓰고 그 오른쪽 칸에 닉네임를 입력해주세요."
	gamedisplay.appendChild(paragraph);
	let mainInputBox = document.createElement("input");
	mainInputBox.setAttribute("id", "input");
	mainInputBox.setAttribute("placeholder", "(ex: 127.0.0.1:8080)");
	mainInputBox.addEventListener("keydown", CheckInputBox);
	gamedisplay.appendChild(mainInputBox);
	let nameInputBox = document.createElement("input");
	nameInputBox.setAttribute("id", "playername");
	nameInputBox.setAttribute("placeholder", "Game Nickname");
	nameInputBox.addEventListener("keydown", CheckInputBox);
	gamedisplay.appendChild(nameInputBox);
	
	function CheckInputBox(e) {
		if (e.keyCode === 13) { // Pressing Enter key
			if (document.getElementById("input").value === "" || document.getElementById("playername").value === "" ) {
				alert("데이터가 없습니다! 빈칸을 내버려두지 마세요!")
				return;
			}
			ip = document.getElementById("input").value;
			playername = document.getElementById("playername").value;
			document.getElementById("input").value = "";
			document.getElementById("playername").value = "";
			document.getElementById("mw-content-text").removeChild(document.getElementById("input"));
			document.getElementById("mw-content-text").removeChild(document.getElementById("playername"));
			document.getElementById("mw-content-text").removeChild(document.getElementById("infoparagraph"));
			DoInitialJob();
		}
	}
}

function createCanvasAndShader () {
	let gamedisplay = document.getElementById("mw-content-text");
	gamedisplay.height = "1080px";
	let baseDiv = document.createElement("div");
	baseDiv.setAttribute("id", "baseDiv");
	baseDiv.style = "z-index:0;display:block;";
	baseDiv.style.position = "absolute";
	baseDiv.width = "1440px";
	baseDiv.height = "1080px";
	baseDiv.style.top = "0px";
	baseDiv.style.left = "0px";
	gamedisplay.appendChild(baseDiv);
	let baseDiv2 = document.createElement("div");
	baseDiv2.setAttribute("id", "baseDiv2");
	baseDiv2.style = "z-index:10;display:block;";
	baseDiv2.style.position = "absolute";
	baseDiv2.width = "1440px";
	baseDiv2.height = "1080px";
	baseDiv2.style.top = "0px";
	baseDiv2.style.left = "0px";
	gamedisplay.appendChild(baseDiv2);
	//create canvases
	let mainCanvas = document.createElement("canvas");
	mainCanvas.setAttribute("id", "MainCanvas");
	mainCanvas.style.border = "none";
	mainCanvas.style.align = "center";
	mainCanvas.setAttribute("width", "800");
	mainCanvas.setAttribute("height", "600");
	baseDiv.appendChild(mainCanvas);
	let uiCanvas = document.createElement("canvas");
	uiCanvas.setAttribute("id", "UICanvas");
	uiCanvas.style.border = "none";
	uiCanvas.style.align = "center";
	uiCanvas.setAttribute("width", "800");
	uiCanvas.setAttribute("height", "600");
	baseDiv2.appendChild(uiCanvas);
	// create shader script(GLSL)
	let vertexshader = document.createElement("script");
	vertexshader.setAttribute("id", "3d-vertex-shader");
	vertexshader.setAttribute("type", "notjs");
	vertexshader.innerText = "\
	attribute vec4 a_position; \
	attribute vec4 a_color; \
	uniform mat4 u_matrix; \
	varying vec4 v_color; \
	void main() { \
		gl_Position = u_matrix * a_position; \
		v_color = a_color; \
	}";
	gamedisplay.appendChild(vertexshader);
	let fragmentshader = document.createElement("script");
	fragmentshader.setAttribute("id", "3d-fragment-shader");
	fragmentshader.setAttribute("type", "notjs");
	fragmentshader.innerText = "\
	precision mediump float; \
	varying vec4 v_color; \
	\
	void main() { \
		gl_FragColor = v_color;\
	}";
	gamedisplay.appendChild(fragmentshader);
	let planevertexshader = document.createElement("script");
	planevertexshader.setAttribute("id", "2d-vertex-shader");
	planevertexshader.setAttribute("type", "notjs");
	planevertexshader.innerText = "\
	attribute vec4 a_position; \
	attribute vec2 a_texcoord; \
	uniform mat4 u_matrix; \
	varying vec2 v_texcoord; \
	void main() { \
	  gl_Position = u_matrix * a_position; \
	  v_texcoord = a_texcoord; \
	}";
	gamedisplay.appendChild(planevertexshader);
	let planefragmentshader = document.createElement("script");
	planefragmentshader.setAttribute("id", "2d-fragment-shader");
	planefragmentshader.setAttribute("type", "notjs");
	planefragmentshader.innerText = "\
	precision mediump float; \
	varying vec2 v_texcoord; \
	uniform sampler2D u_texture; \
	void main() { \
	   gl_FragColor = texture2D(u_texture, v_texcoord);\
	   gl_FragColor.rgb *= gl_FragColor.a;\
	}";
	gamedisplay.appendChild(planefragmentshader);
	return;
}

createIPInputBox ();

// ------------------------------------------------------------------------------------------------------------
// ----------------------------------------- put your own code here -------------------------------------------
// ------------------------------------------------------------------------------------------------------------

// ----------------------------------------------------------------------------------------------------
// --------------------------- UncycloFortress client-side Script -------------------------------------
// ----------------------------------------------------------------------------------------------------

let scriptversion = 0.1;
let inputhandler;

function Projectile_Rocket(pos, size, direction, team, shooter, imgsrc) {
	Projectile.call(this, pos, size, direction, team, shooter, imgsrc);
	this.vertexlist = GenerateProjectile(this.GetCenterPosition(), this.size, this.cameraMatrix);
}
Projectile_Rocket.prototype = Object.create(Projectile.prototype);
Projectile_Rocket.prototype.constructor = Projectile_Rocket;

function Weapon (type, owner) {
	this.type = type;
	this.owner = owner;
	this.timerhandler;
	this.loadedbullet = 1;
	this.firedelay = 1000;
	this.reloaddelay = 1000;
	this.isReloading = false;
	this.isFiring = false;
	this.MaxAmmo = this.loadedbullet;
	this.weaponname = "?";
	this.ReloadWeapon = () => {
		this.isFiring = false; 
		if (!this.isReloading && this.loadedbullet != this.MaxAmmo){
			clearTimeout(this.timerhandler);
			this.timerhandler = setTimeout(this.ReloadWeapon_sub, this.reloaddelay);
			this.isReloading = true;
		}
	};
	this.ReloadWeapon_sub = () => {
		// use fetch to fire event and get result
		// apply the result
			// if result failed(due to timing or else)
			// if result is success
			this.loadedbullet = this.MaxAmmo;
			this.isReloading = false;
			ws.send(JSON.stringify({
				type: 13,
				id: player.playerID,
				currentweapon: player.currentweapon
			}));
		return;
	}
	this.FireWeapon = () =>{
		if (this.type != 9 && this.loadedbullet === 0 && !this.isReloading) {
			this.ReloadWeapon();
		} else if (!this.isReloading && !this.isFiring) {
			// use fetch to fire event and get result
			// apply the result
				// if result failed(due to timing or else)
				// if result is success
			clearTimeout(this.timerhandler);
			this.timerhandler = setTimeout(this.FireWeapon_sub, this.firedelay);
			this.isFiring = true;
		}
	};
	this.FireWeapon_sub = () => {
		this.isFiring = false;
	};
	this.ReleaseFire = () => {
		return;
	};
	this.DoSpecialSkill = () => {
		// use fetch to fire event and get result
		// apply the result
			// if result failed(due to timing or else)
			// if result is success
	};
}
function Weapon_Pistol (type, owner) {
	Weapon.call(this, type, owner);
	this.loadedbullet = 6;
	this.firedelay = 300;
	this.reloaddelay = 1000;
	this.MaxAmmo = this.loadedbullet;
	this.weaponname = "Pistol";
	this.FireWeapon = () =>{
		if (this.type != 9 && this.loadedbullet === 0 && !this.isReloading) {
			this.ReloadWeapon();
		} else if (!this.isReloading && !this.isFiring) {
			// use fetch to fire event and get result
			// apply the result
				// if result failed(due to timing or else)
				// if result is success
				if (this.type != 9 && this.loadedbullet > 0)this.loadedbullet -= 1;
				this.owner.raylist = new Array(1);
				let randomNum = Math.random();
				this.owner.raylist[0] = new Ray ([this.owner.GetCenterPosition()[0], this.owner.GetCenterPosition()[1], -18], [this.owner.GetCenterPosition()[0]- 10000* Math.cos(this.owner.direction+Math.PI/2- Math.PI/360+randomNum* Math.PI/180), this.owner.GetCenterPosition()[1] - 10000*  Math.sin(this.owner.direction +Math.PI/2 - Math.PI/360+randomNum* Math.PI/180), 0]);
				ws.send(JSON.stringify({
					type:6,
					id:player.playerID,
					raylist: [{startpos:[this.owner.GetCenterPosition()[0], this.owner.GetCenterPosition()[1], -18], endpos: [this.owner.GetCenterPosition()[0]- 10000* Math.cos(this.owner.direction+Math.PI/2- Math.PI/360+randomNum* Math.PI/180), this.owner.GetCenterPosition()[1] - 10000*  Math.sin(this.owner.direction +Math.PI/2 - Math.PI/360+randomNum* Math.PI/180), 0]}]
				}));
				this.owner.raylist[0].AddPenetratingObjects(mapinfo.mapobjectlist);
				this.owner.raylist[0].endpos = this.owner.raylist[0].GetClosestCollidedPosition();
				this.owner.raylist[0].DrawRay();
			clearTimeout(this.timerhandler);
			this.timerhandler = setTimeout(this.FireWeapon_sub, this.firedelay);
			this.isFiring = true;
		}
	};
	this.FireWeapon_sub = () => {
		this.isFiring = false;
	};
	this.ReleaseFire = () => {
		return;
	}
}
Weapon_Pistol.prototype = Object.create(Weapon.prototype);
Weapon_Pistol.prototype.constructor = Weapon_Pistol;

function Weapon_PowerShotgun (type, owner) {
	Weapon.call(this, type, owner);
	this.loadedbullet = 4;
	this.firedelay = 800;
	this.reloaddelay = 1000;
	this.MaxAmmo = this.loadedbullet;
	this.weaponname = "Power Shotgun";
	this.FireWeapon = () =>{
		if (this.type != 9 && this.loadedbullet === 0 && !this.isReloading) {
			this.ReloadWeapon();
		} else if (!this.isReloading && !this.isFiring) {
			// use fetch to fire event and get result
			// apply the result
				// if result failed(due to timing or else)
				// if result is success
				if (this.type != 9 && this.loadedbullet > 0)this.loadedbullet -= 1;
				this.owner.raylist = new Array(9);
				let raylist = [];
				for (let i = 0 ; i < 9; i++) { // 9 < MAX_RAY_PER_PERSON
					this.owner.raylist[i] = new Ray ([this.owner.GetCenterPosition()[0], this.owner.GetCenterPosition()[1], -18], [this.owner.GetCenterPosition()[0]- 10000* Math.cos(this.owner.direction+Math.PI/2- Math.PI/12+i* Math.PI/48), this.owner.GetCenterPosition()[1] - 10000*  Math.sin(this.owner.direction +Math.PI/2- Math.PI/12+i* Math.PI/48), 0]);
					raylist.push({startpos:[this.owner.GetCenterPosition()[0], this.owner.GetCenterPosition()[1], -18], endpos: [this.owner.GetCenterPosition()[0]- 10000* Math.cos(this.owner.direction+Math.PI/2- Math.PI/12+i* Math.PI/48), this.owner.GetCenterPosition()[1] - 10000*  Math.sin(this.owner.direction +Math.PI/2- Math.PI/12+i* Math.PI/48), 0]});
				}
				ws.send(JSON.stringify({
					type:6,
					id:player.playerID,
					raylist: raylist
				}));
				for (let i = 0 ; i < 9 ; i++) {
					this.owner.raylist[i].AddPenetratingObjects(mapinfo.mapobjectlist);
					this.owner.raylist[i].endpos = this.owner.raylist[i].GetClosestCollidedPosition();
					this.owner.raylist[i].DrawRay();
				}
			clearTimeout(this.timerhandler);
			this.timerhandler = setTimeout(this.FireWeapon_sub, this.firedelay);
			this.isFiring = true;
		}
	};
	this.FireWeapon_sub = () => {
		this.isFiring = false;
	};
	this.ReleaseFire = () => {
		return;
	}
}
Weapon_PowerShotgun.prototype = Object.create(Weapon.prototype);
Weapon_PowerShotgun.prototype.constructor = Weapon_PowerShotgun;
function Weapon_Minigun (type, owner) {
	Weapon.call(this, type, owner);
	this.loadedbullet = 200;
	this.firedelay = 100;
	this.reloaddelay = 5000;
	this.MaxAmmo = this.loadedbullet;
	this.weaponname = "Minigun";
	this.FireWeapon = () =>{
		if (this.type != 9 && this.loadedbullet === 0 && !this.isReloading) {
			this.ReloadWeapon();
		} else if (!this.isReloading && !this.isFiring) {
			// use fetch to fire event and get result
			// apply the result
				// if result failed(due to timing or else)
				// if result is success
				if (this.type != 9 && this.loadedbullet > 0)this.loadedbullet -= 1;
				this.owner.raylist = new Array(2);
				let raylist = [];
				for (let i = 0 ; i < 2; i++) { // 2 < MAX_RAY_PER_PERSON
					let randomNum = Math.random();
					this.owner.raylist[i] = new Ray ([this.owner.GetCenterPosition()[0], this.owner.GetCenterPosition()[1], -18], [this.owner.GetCenterPosition()[0]- 10000* Math.cos(this.owner.direction+Math.PI/2- Math.PI/24+randomNum* Math.PI/12), this.owner.GetCenterPosition()[1] - 10000*  Math.sin(this.owner.direction +Math.PI/2 - Math.PI/24+randomNum* Math.PI/12), 0]);
					raylist.push({startpos:[this.owner.GetCenterPosition()[0], this.owner.GetCenterPosition()[1], -18], endpos: [this.owner.GetCenterPosition()[0]- 10000* Math.cos(this.owner.direction+Math.PI/2- Math.PI/24+randomNum* Math.PI/12), this.owner.GetCenterPosition()[1] - 10000*  Math.sin(this.owner.direction +Math.PI/2 - Math.PI/24+randomNum* Math.PI/12), 0]});
				}
				ws.send(JSON.stringify({
					type:6,
					id:player.playerID,
					raylist: raylist
				}));
				for (let i = 0 ; i < 2; i++) { // 2 < MAX_RAY_PER_PERSON
					this.owner.raylist[i].AddPenetratingObjects(mapinfo.mapobjectlist);
					this.owner.raylist[i].endpos = this.owner.raylist[i].GetClosestCollidedPosition();
					this.owner.raylist[i].DrawRay();
				}
			clearTimeout(this.timerhandler);
			this.timerhandler = setTimeout(this.FireWeapon_sub, this.firedelay);
			this.isFiring = true;
		}
	};
	this.FireWeapon_sub = () => {
		if (this.loadedbullet > 0 ){
			// use fetch to fire event and get result
			// apply the result
				// if result failed(due to timing or else)
				// if result is success
				this.loadedbullet -= 1;
				this.owner.raylist = new Array(2);
				let raylist = [];
				for (let i = 0 ; i < 2; i++) { // 2 < MAX_RAY_PER_PERSON
					let randomNum = Math.random();
					this.owner.raylist[i] = new Ray ([this.owner.GetCenterPosition()[0], this.owner.GetCenterPosition()[1], -18], [this.owner.GetCenterPosition()[0]- 10000* Math.cos(this.owner.direction+Math.PI/2- Math.PI/24+randomNum* Math.PI/12), this.owner.GetCenterPosition()[1] - 10000*  Math.sin(this.owner.direction +Math.PI/2 - Math.PI/24+randomNum* Math.PI/12), 0]);
					raylist.push({startpos:[this.owner.GetCenterPosition()[0], this.owner.GetCenterPosition()[1], -18], endpos: [this.owner.GetCenterPosition()[0]- 10000* Math.cos(this.owner.direction+Math.PI/2- Math.PI/24+randomNum* Math.PI/12), this.owner.GetCenterPosition()[1] - 10000*  Math.sin(this.owner.direction +Math.PI/2 - Math.PI/24+randomNum* Math.PI/12), 0]});
				}
				ws.send(JSON.stringify({
					type:6,
					id:player.playerID,
					raylist: raylist
				}));
				for (let i = 0 ; i < 2; i++) { // 2 < MAX_RAY_PER_PERSON
					this.owner.raylist[i].AddPenetratingObjects(mapinfo.mapobjectlist);
					this.owner.raylist[i].endpos = this.owner.raylist[i].GetClosestCollidedPosition();
					this.owner.raylist[i].DrawRay();
				}
			this.timerhandler = setTimeout(this.FireWeapon_sub, this.firedelay);
		}
	};
	this.ReleaseFire = () => {
		if (this.isFiring) {
			clearTimeout(this.timerhandler);
			this.isFiring = false;
		}
		return;
	}
}
Weapon_Minigun.prototype = Object.create(Weapon.prototype);
Weapon_Minigun.prototype.constructor = Weapon_Minigun;
function Weapon_RocketLauncher (type, owner) {
	Weapon.call(this, type, owner);
	this.loadedbullet = 6;
	this.firedelay = 800;
	this.reloaddelay = 1000;
	this.MaxAmmo = this.loadedbullet;
	this.weaponname = "Rocket Launcher";
	this.FireWeapon = () =>{
		if (this.type != 9 && this.loadedbullet === 0 && !this.isReloading) {
			this.ReloadWeapon();
		} else if (!this.isReloading && !this.isFiring) {
			// use fetch to fire event and get result
			// apply the result
				// if result failed(due to timing or else)
				// if result is success
				if (this.type != 9 && this.loadedbullet > 0)this.loadedbullet -= 1;
				let tempprojectile = new Projectile_Rocket([this.owner.GetCenterPosition()[0] - 8, this.owner.GetCenterPosition()[1] - 8], 1, this.owner.direction, 1, this.owner, "UF_Rocket_Red.png");
				tempprojectile.visible = true;
				if (projectilelist.length < MAX_PROJECTILE_NUMBER)projectilelist.push(tempprojectile);
				ws.send(JSON.stringify({
					type:7,
					id:player.playerID,
					pos: [this.owner.GetCenterPosition()[0] - 8, this.owner.GetCenterPosition()[1] - 8],
					direction:this.owner.direction,
					shooterid: this.owner.playerID,
					projectiletype: 0
				}));
			clearTimeout(this.timerhandler);
			this.timerhandler = setTimeout(this.FireWeapon_sub, this.firedelay);
			this.isFiring = true;
		}
	};
	this.FireWeapon_sub = () => {
		this.isFiring = false;
	};
	this.ReleaseFire = () => {
		return;
	}
}
Weapon_RocketLauncher.prototype = Object.create(Weapon.prototype);
Weapon_RocketLauncher.prototype.constructor = Weapon_RocketLauncher;

function DoSomethingAfterMapLoad () {
	// add class selection button
	let gamedisplay = document.getElementById("mw-content-text");

	let classbutton1 = document.createElement("button");
	classbutton1.setAttribute("name", "classbutton1");
	classbutton1.setAttribute("type", "button");
	classbutton1.setAttribute("value", "1");
	classbutton1.innerText = "Speedster";
	classbutton1.onclick = ChangeMyCharacter;
	gamedisplay.appendChild(classbutton1);
	let classbutton2 = document.createElement("button");
	classbutton2.setAttribute("name", "classbutton2");
	classbutton2.setAttribute("type", "button");
	classbutton2.setAttribute("value", "2");
	classbutton2.innerText = "Tank";
	classbutton2.onclick = ChangeMyCharacter;
	gamedisplay.appendChild(classbutton2);
	let classbutton3 = document.createElement("button");
	classbutton3.setAttribute("name", "classbutton3");
	classbutton3.setAttribute("type", "button");
	classbutton3.setAttribute("value", "3");
	classbutton3.innerText = "Tankbuster";
	classbutton3.onclick = ChangeMyCharacter;
	gamedisplay.appendChild(classbutton3);
	// spawn initial player
	player = new Player([mapinfo.RedSpawn[0], mapinfo.RedSpawn[1]], 8, [degToRad(0), degToRad(0), degToRad(0)], degToRad(0), 1, 0);
	player.secondweapon = new Weapon(0,player); // weapon 0
	player.firstweapon = new Weapon(4,player); // weapon 1
	player.currentweapon = 0;
	player.ReloadWeapon = () => {
	};
	player.FireWeapon = () =>{
	};
	player.DoSpecialSkill = () => {
	};
	player.ReleaseFire = () => {
	};
	gamerule = new GameRule(180, 180, 0);
	inputhandler = new Input(document.getElementById("UICanvas"));
	inputhandler.InitInput();
	return;
}

function DrawUI () {
	if (player != undefined && player.secondweapon != undefined && player.firstweapon != undefined){
		let ctx = document.getElementById("UICanvas").getContext("2d");
		ctx.canvas.width = 800; // reset the ui canvas
		ctx.beginPath();
		ctx.rect(0, 500, 800, 100);
		ctx.fillStyle = "rgba(125, 125, 5, 1)";
		ctx.fill();
		ctx.font = "18px Arial, sans-serif";
		ctx.fillStyle = "rgba(255, 255, 0, 1)";
		if (player.currentweapon === 0)ctx.fillText("Current Weapon: "+ player.secondweapon.weaponname,20,20);
		else ctx.fillText("Current Weapon: "+ player.firstweapon.weaponname,20,20);
		ctx.fillStyle = "rgba(255, 0, 0, 1)";
		ctx.fillText(String.format("{0}:{1}", Math.floor(gamerule.RedClock /60), gamerule.RedClock % 60),400-90,20 );
		ctx.fillStyle = "rgba(25, 125, 255, 1)";
		ctx.fillText(String.format("{0}:{1}", Math.floor(gamerule.BlueClock /60), gamerule.BlueClock % 60),400,20 );
		// reserved for kill log
		
		ctx.fillStyle = "rgba(255, 255, 0, 1)";
		ctx.fillText("Health: "+player.healthpoint, 20, 580);
		if (player.currentweapon === 0) {
			if (player.secondweapon.isReloading) {
				ctx.fillStyle = "rgba(255, 25, 0, 1)";
				ctx.fillText("Reloading", 700, 560);
			}
			ctx.fillText("Ammo: "+player.secondweapon.loadedbullet, 700, 580);
		} else {
			if (player.firstweapon.isReloading) {
				ctx.fillStyle = "rgba(255, 25, 0, 1)";
				ctx.fillText("Reloading", 700, 560);
			}
			ctx.fillText("Ammo: "+player.firstweapon.loadedbullet, 700, 580);
		}
		ctx.closePath();
		ctx.beginPath();
		ctx.arc(400, 300, 10, 0, 2*Math.PI, true);
		ctx.closePath();
		ctx.lineWidth = 2;
		ctx.strokeStyle = "#FFFF00";
		ctx.stroke();
		ctx.beginPath();
		ctx.font = "12px Arial, sans-serif";
		for (let killlog of killloglist){
			ctx.fillStyle = "rgba(0, 255, 0, 1)";
			ctx.fillText(killlog, 760 - 5*killlog.length, 40+8*killloglist.indexOf(killlog));
		}
		ctx.closePath();
		if (keystate[7]){
			//draw player list board
			ctx.beginPath();
			ctx.rect(100, 100, 600, 600);
			ctx.fillStyle = "rgba(0, 0, 0, 0.5)";
			ctx.fill();
			ctx.font = "18px Arial, sans-serif";
			ctx.fillStyle = "rgba(0, 255, 0, 1)";
			ctx.fillText("Players", 400 - "Players".length / 2, 110);
			let blueteamplayer = 0;
			let redteamplayer = 0;
			for (let playeritem of playerlist) {
				if (playeritem.team === 1 ) {
					ctx.fillStyle = "rgba(255, 0, 0, 1)";
					ctx.fillText(playeritem.playername, 660 - 8*playeritem.playername.length, 140+9*redteamplayer);
					redteamplayer += 1;
				} else if (playeritem.team === 2) {
					ctx.fillStyle = "rgba(0, 0, 255, 1)";
					ctx.fillText(playeritem.playername, 140, 140+9*blueteamplayer);
					blueteamplayer += 1;
				}
			}
			ctx.closePath();
		}
	}
	return;
}

function GetMyNewWeapon(type) {
	let newweapon = new Weapon(type,player);
	switch (type) {
		case 0: // pistol
			newweapon = new Weapon_Pistol(type, player);
			break;
		case 1: // nail gun
			newweapon.loadedbullet = 30;
			newweapon.firedelay = 200;
			newweapon.reloaddelay = 1000;
			break;
		case 2: // short shotgun
			newweapon.loadedbullet = 8;
			newweapon.firedelay = 400;
			newweapon.reloaddelay = 2000;
			break;
		case 4: // power shotgun
			newweapon = new Weapon_PowerShotgun(type, player);
			break;
		case 5: // minigun
			newweapon = new Weapon_Minigun (type, player);
			break;
		case 6: // rocket shooter
			newweapon = new Weapon_RocketLauncher (type, player);
			break;
		case 7: // medibeam shooter
			newweapon.loadedbullet = -1;
			newweapon.firedelay = 200;
			newweapon.reloaddelay = 0;
			break;
		case 8: // watershooter
			newweapon.loadedbullet = -1;
			newweapon.firedelay = 200;
			newweapon.reloaddelay = 0;
			break;
		case 9: // wrench
			newweapon.loadedbullet = 200;
			newweapon.firedelay = 800;
			newweapon.reloaddelay = 1000;
			break;
		case 10: // pipe shooter
			newweapon.loadedbullet = 8;
			newweapon.firedelay = 400;
			newweapon.reloaddelay = 2000;
			break;
		case 11: // sniper rifle
			newweapon.loadedbullet = 1;
			newweapon.firedelay = 400;
			newweapon.reloaddelay = 2000;
			break;
		case 12: // knife
			newweapon.loadedbullet = -1;
			newweapon.firedelay = 800;
			newweapon.reloaddelay = 1000;
			break;
		default:
			newweapon.loadedbullet = 1;
			newweapon.firedelay = 400;
			newweapon.reloaddelay = 1000;
			break;
	}
	newweapon.MaxAmmo = newweapon.loadedbullet;
	return newweapon;
}

function ChangeMyCharacter(event) {
	inputhandler.ReleasePlayer();
	switch(event.target.value) {
		case "1":
			if (player.team === 1) {
				player = new Player(player.pos, 12, degToRad(0), player.team, 100, player.playerID, true, player.playername, 1);
			} else {
				player = new Player(player.pos, 12, degToRad(180), player.team, 100, player.playerID, true, player.playername, 1);
			}
			player.secondweapon = GetMyNewWeapon(0); // weapon 0
			player.firstweapon = GetMyNewWeapon(4); // weapon 1
			player.movespeed = 2;
			break;
		case "2":
			if (player.team === 1) {
				player = new Player(player.pos, 12, degToRad(0), player.team, 300, player.playerID, true, player.playername, 2);
			} else {
				player = new Player(player.pos, 12, degToRad(180), player.team, 300, player.playerID, true, player.playername, 2);
			}
			player.secondweapon = GetMyNewWeapon(0); // weapon 0
			player.firstweapon = GetMyNewWeapon(5); // weapon 1
			player.movespeed = 0.5;
			break;
		case "3":
			if (player.team === 1) {
				player = new Player(player.pos, 12, degToRad(0), player.team, 200, player.playerID, true, player.playername, 3);
			} else {
				player = new Player(player.pos, 12, degToRad(180), player.team, 200, player.playerID, true, player.playername, 3);
			}
			player.secondweapon = GetMyNewWeapon(0); // weapon 0
			player.firstweapon = GetMyNewWeapon(6); // weapon 1
			player.movespeed = 1;
			break;
		default:
			//only possible in initial entrance
			break;
	}
	if (player.team === 1) {
	player.SetCenterPosition([mapinfo.RedSpawn[0] + mapobjectsizeconstant/2, mapinfo.RedSpawn[1] + mapobjectsizeconstant/2]);
	} else {
		player.SetCenterPosition([mapinfo.BlueSpawn[0] + mapobjectsizeconstant/2, mapinfo.BlueSpawn[1] + mapobjectsizeconstant/2]);
	}
	player.currentweapon = 0;
	ws.send(JSON.stringify({
		type:3,
		id:player.playerID,
		classnum:player.classnumber,
		team: player.team
	}));
	clearTimeout(player.deadtimer);
	player.deadtimer = setTimeout(deadStateHandler, 4000);
	return;
}