<commit_before>'use strict';

var informationSection = (function() {
  // cache DOM
  var $informationSec;
  var $contentArea;

  function _initialize() {
    $informationSec = $("#information-section");

    // Close ibox function
    $informationSec.find(".aside-close-link").click(function() {
      adjustAsideArea();
    });
  }

  function adjustAsideArea(isOpen) {
    var chatSection = $('#chat-section');
    var asideIbox = $("#information-section .ibox");
    if(isOpen || chatSection.hasClass("col-xs-12 col-lg-12")) {
      chatSection.removeClass("col-xs-12 col-lg-12").addClass( "col-xs-9 col-lg-9" );
      asideIbox.show(500);
    } else {
      chatSection.removeClass("col-xs-9 col-lg-9").addClass( "col-xs-12 col-lg-12" );
      asideIbox.hide();
    }
  }

  function initAsideSection() {
    _initialize()
  }

  function resizeInformationSection() {
    var windowHeight = $(window).height();
    var headerHeight = $("#header-section").outerHeight(true);
    var informationHeaderHeight =  $informationSec.find(".ibox-title").outerHeight(true);
    var informationHeight =  windowHeight - headerHeight - informationHeaderHeight;
    $informationSec.find(".ibox-content").css("height", informationHeight);
  }

  function showAboutUser(callHistoryData) {
    loadHtml("./html/information/about_user.html", $informationSec);
    var aboutUserTemplate = $informationSec.find('#aboutUser-template').html();
    var callHistoryTemplate = $informationSec.find('#callHistory-template').html();
    var $title = $informationSec.find(".title");
    var $contentArea = $informationSec.find('.content_area');

    var emplId = activeChatInfo.chatRoomId;
    var userValue = catalogSection.getUserObj(emplId);
    var aboutUserData = {
      "loginId" : userValue.loginId,
      "imgAlt" : userValue.loginId,
      "img": "../img/profile_img" + userValue.emplId + ".jpg",
    };

    $title.html("About this conversation");
    $contentArea.find("#about-user").append(Mustache.render(aboutUserTemplate, aboutUserData));

    $contentArea.find(".call").click(function() {
      callSection.showSection();
      chatSection.hideSection(); // chat Area
      callSection.showCallInfo(emplId, userValue.loginId);
    });

    // TODO 현재는 사용자 선택시마다 API 호출 -> 캐시 기능 필요 ?
    var restPrams = {
      "coId": myPref.coId,
      "caller": myPref.emplId,
      "callee": activeChatInfo.chatRoomId
    };

    restResourse.callHistory.getListByCondition(restPrams, function(commonGridValue) {
      console.log("commonGridValue[totalPage:%d, totalRecords:%d]", commonGridValue.totalPage, commonGridValue.totalRecords);

      var callHistoryList = commonGridValue.rows;
      $.each(callHistoryList, function(idx, callHistoryRow) {
        callHistoryRow.callStart = new Date(callHistoryRow.callStart).format("YYYY/MM/DD a HH:mm");
      });

      var callHistoryData = {
        "callHistoryList" : callHistoryList
      };

      $contentArea.append(Mustache.render(callHistoryTemplate, callHistoryData));
      $contentArea.find(".onDetailHistoryModal").bind("click", function() {
        var callHistoryId = $(this).closest("li").data("callhistoryid") ;
        console.log(callHistoryId);
        var sendingData = {"callhistoryid" : callHistoryId };
        openModalDialog("./html/information/popup/detail_callhistory_popup.html", null, sendingData);
      });
    });

    resizeInformationSection();
    _informationSectionScroll();
    $informationSec.show();
  }

  function showAboutChannel() {
    loadHtml("./html/information/about_channel.html", $informationSec);
    var aboutChannelTemplate = $informationSec.find('#aboutChannel-template').html();
    var $title = $informationSec.find(".title");
    var $contentArea = $informationSec.find('.content_area');

    var channelId = activeChatInfo.chatRoomId;
    var channelValue = catalogSection.getChannelObj(channelId);
    var existMembers;
    for(var key in channelValue.memberList) {
      var emplId = channelValue.memberList[key].emplId;
      if(!existMembers)
        existMembers = emplId;
      else
        existMembers += "," + channelValue.memberList[key].emplId;
    }
    var membersArray = String(existMembers).split(",");
    var memberCount = membersArray.length;

    $title.html("About #" + channelValue.name);
    var aboutChannelData = {
      "pinupMessage": channelValue.pinupMessage || "There are no purpose.",
      "memberCount": memberCount,
      "members":[]
    };

    for(var key in membersArray) {
      var userValue = catalogSection.getUserObj(membersArray[key]);
      aboutChannelData.members.push({
        "loginId" : userValue.loginId,
        "emplId" : userValue.emplId,
        "imgAlt" : userValue.loginId,
        "img": "../img/profile_img" + userValue.emplId + ".jpg",
      });
    }

    $contentArea.empty();
    $contentArea.prepend(Mustache.render(aboutChannelTemplate, aboutChannelData));

    $("#onInviteChannelModal").bind("click", function() {
      openModalDialog("./html/information/popup/invite_channel_popup.html");
    });

    $contentArea.find(".leaveChannel").click(function() {
      var params = {
        "channelId": channelId,
        "members": myPref.emplId,
      };

      restResourse.channel.removeMember(params,
        function(response) {
          if(response.statusCode === 200) {

            var channelValue = catalogSection.getChannelObj(channelId);
            if(channelValue) {
              var members;
              for(var key in channelValue.memberList) {
                var emplId = channelValue.memberList[key].emplId;

                var params = {
                  "type": constants.GROUP_REMOVE_MEMBER,
                  "channelId": channelId,
                  "member": myPref.emplId
                }

                chatModule.sendCommand(emplId, params);
              }
            }

            chatSection.sendMsg("left - " + myPref.loginId, constants.GROUP_CHAT, channelId); // 멤버 삭제 메시지 전송
          } else {
            console.log("[fail add memeber]" + response.statusMessage);
          }
        }
      );
    });

    resizeInformationSection();
    _informationSectionScroll();
    $informationSec.show();
  }

  function showMentionList(messages) {
    loadHtml("./html/information/mention_list.html", $informationSec);

    var mentionTemplate = $informationSec.find('#mention-template').html();
    var mentionDateLineTemplate = $informationSec.find('#mention-dateline-template').html();
    var $title = $informationSec.find(".title");
    var $contentArea = $informationSec.find('.content_area');

    var params = {
      "emplId": myPref.emplId
    };

    restResourse.chat.getMentionList(params, function(data) {
      if (data) {
        var messages = [];
        $.each(data, function(idx, row) {
          var sender = catalogSection.getUserObj(row.spkrId);
          var channel = catalogSection.getChannelObj(row.peer2);
          var message = {
            "msgId": row.chatId,
            "img": "../img/profile_img" + row.spkrId + ".jpg",
            "imgAlt": sender.loginId,
            "channel": channel ? channel.name : "unknown",
            "sender": sender.loginId,
            "msgText": row.msg,
            "date": new Date(row.creTime).format("yyyy/MM/dd"),
            "time": new Date(row.creTime).format("a hh mm")
          };

          messages.push(message);
        });

        $contentArea.empty();
        $title.html("Mention #" + myPref.loginId);
        for (var key = 0; key < messages.length; key++) {
          if(key === 0) {
            $contentArea.append(Mustache.render(mentionDateLineTemplate, {"date" : messages[key].date}));
          }
          if(messages[key - 1] && messages[key - 1].date != messages[key].date) {
            $contentArea.append(Mustache.render(mentionDateLineTemplate, {"date" : messages[key].date}));
          }
          $contentArea.append(Mustache.render(mentionTemplate, messages[key]));
        }
      }
    });
    resizeInformationSection();
    _informationSectionScroll();
    $informationSec.show();
  }

  function displayMember(members) {
    var $contentArea = $informationSec.find('.content_area');
    for(var key in members) {
      var userValue = catalogSection.getUserObj(members[key]);
      var imgUrl = "../img/profile_img" + userValue.emplId + ".jpg";
      $contentArea.find(".members").append("
" + userValue.loginId + "
");
    }
  }

  function hideMember(member) {
    var $contentArea = $informationSec.find('.content_area');
    $contentArea.find(".members [data-emplid='" + member + "']").remove();
  }

  function hideSection() {
    $informationSec.hide();
  }

  function showSection() {
    $informationSec.show();
  }

  function _informationSectionScroll() {
    $informationSec.find(".ibox-content").mCustomScrollbar({
      axis:"y",
  		setWidth: "auto",
      theme:"3d"
    });
  }

  return {
    initAsideSection: initAsideSection,
    resizeInformationSection: resizeInformationSection,
    showAboutChannel: showAboutChannel,
    showAboutUser: showAboutUser,
    adjustAsideArea: adjustAsideArea,
    displayMember: displayMember,
    showMentionList: showMentionList,
    hideMember: hideMember,
    hideSection: hideSection
  };
})();

module.exports = informationSection;
<commit_msg>revert missing method<commit_after>'use strict';

var informationSection = (function() {
  // cache DOM
  var $informationSec;
  var $contentArea;

  function _initialize() {
    $informationSec = $("#information-section");

    // Close ibox function
    $informationSec.find(".aside-close-link").click(function() {
      adjustAsideArea();
    });
  }

  function adjustAsideArea(isOpen) {
    var chatSection = $('#chat-section');
    var asideIbox = $("#information-section .ibox");
    if(isOpen || chatSection.hasClass("col-xs-12 col-lg-12")) {
      chatSection.removeClass("col-xs-12 col-lg-12").addClass( "col-xs-9 col-lg-9" );
      asideIbox.show(500);
    } else {
      chatSection.removeClass("col-xs-9 col-lg-9").addClass( "col-xs-12 col-lg-12" );
      asideIbox.hide();
    }
  }

  function initAsideSection() {
    _initialize()
  }

  function resizeInformationSection() {
    var windowHeight = $(window).height();
    var headerHeight = $("#header-section").outerHeight(true);
    var informationHeaderHeight =  $informationSec.find(".ibox-title").outerHeight(true);
    var informationHeight =  windowHeight - headerHeight - informationHeaderHeight;
    $informationSec.find(".ibox-content").css("height", informationHeight);
  }

  function showAboutUser(callHistoryData) {
    loadHtml("./html/information/about_user.html", $informationSec);
    var aboutUserTemplate = $informationSec.find('#aboutUser-template').html();
    var callHistoryTemplate = $informationSec.find('#callHistory-template').html();
    var $title = $informationSec.find(".title");
    var $contentArea = $informationSec.find('.content_area');

    var emplId = activeChatInfo.chatRoomId;
    var userValue = catalogSection.getUserObj(emplId);
    var aboutUserData = {
      "loginId" : userValue.loginId,
      "imgAlt" : userValue.loginId,
      "img": "../img/profile_img" + userValue.emplId + ".jpg",
    };

    $title.html("About this conversation");
    $contentArea.find("#about-user").append(Mustache.render(aboutUserTemplate, aboutUserData));

    $contentArea.find(".call").click(function() {
      callSection.showSection();
      chatSection.hideSection(); // chat Area
      callSection.showCallInfo(emplId, userValue.loginId);
    });

    // TODO 현재는 사용자 선택시마다 API 호출 -> 캐시 기능 필요 ?
    var restPrams = {
      "coId": myPref.coId,
      "caller": myPref.emplId,
      "callee": activeChatInfo.chatRoomId
    };

    restResourse.callHistory.getListByCondition(restPrams, function(commonGridValue) {
      console.log("commonGridValue[totalPage:%d, totalRecords:%d]", commonGridValue.totalPage, commonGridValue.totalRecords);

      var callHistoryList = commonGridValue.rows;
      $.each(callHistoryList, function(idx, callHistoryRow) {
        callHistoryRow.callStart = new Date(callHistoryRow.callStart).format("YYYY/MM/DD a HH:mm");
      });

      var callHistoryData = {
        "callHistoryList" : callHistoryList
      };

      $contentArea.append(Mustache.render(callHistoryTemplate, callHistoryData));
      $contentArea.find(".onDetailHistoryModal").bind("click", function() {
        var callHistoryId = $(this).closest("li").data("callhistoryid") ;
        console.log(callHistoryId);
        var sendingData = {"callhistoryid" : callHistoryId };
        openModalDialog("./html/information/popup/detail_callhistory_popup.html", null, sendingData);
      });
    });

    resizeInformationSection();
    _informationSectionScroll();
    $informationSec.show();
  }

  function showAboutChannel() {
    loadHtml("./html/information/about_channel.html", $informationSec);
    var aboutChannelTemplate = $informationSec.find('#aboutChannel-template').html();
    var $title = $informationSec.find(".title");
    var $contentArea = $informationSec.find('.content_area');

    var channelId = activeChatInfo.chatRoomId;
    var channelValue = catalogSection.getChannelObj(channelId);
    var existMembers;
    for(var key in channelValue.memberList) {
      var emplId = channelValue.memberList[key].emplId;
      if(!existMembers)
        existMembers = emplId;
      else
        existMembers += "," + channelValue.memberList[key].emplId;
    }
    var membersArray = String(existMembers).split(",");
    var memberCount = membersArray.length;

    $title.html("About #" + channelValue.name);
    var aboutChannelData = {
      "pinupMessage": channelValue.pinupMessage || "There are no purpose.",
      "memberCount": memberCount,
      "members":[]
    };

    for(var key in membersArray) {
      var userValue = catalogSection.getUserObj(membersArray[key]);
      aboutChannelData.members.push({
        "loginId" : userValue.loginId,
        "emplId" : userValue.emplId,
        "imgAlt" : userValue.loginId,
        "img": "../img/profile_img" + userValue.emplId + ".jpg",
      });
    }

    $contentArea.empty();
    $contentArea.prepend(Mustache.render(aboutChannelTemplate, aboutChannelData));

    $("#onInviteChannelModal").bind("click", function() {
      openModalDialog("./html/information/popup/invite_channel_popup.html");
    });

    $contentArea.find(".leaveChannel").click(function() {
      var params = {
        "channelId": channelId,
        "members": myPref.emplId,
      };

      restResourse.channel.removeMember(params,
        function(response) {
          if(response.statusCode === 200) {

            var channelValue = catalogSection.getChannelObj(channelId);
            if(channelValue) {
              var members;
              for(var key in channelValue.memberList) {
                var emplId = channelValue.memberList[key].emplId;

                var params = {
                  "type": constants.GROUP_REMOVE_MEMBER,
                  "channelId": channelId,
                  "member": myPref.emplId
                }

                chatModule.sendCommand(emplId, params);
              }
            }

            chatSection.sendMsg("left - " + myPref.loginId, constants.GROUP_CHAT, channelId); // 멤버 삭제 메시지 전송
          } else {
            console.log("[fail add memeber]" + response.statusMessage);
          }
        }
      );
    });

    resizeInformationSection();
    _informationSectionScroll();
    $informationSec.show();
  }

  function showMentionList(messages) {
    loadHtml("./html/information/mention_list.html", $informationSec);

    var mentionTemplate = $informationSec.find('#mention-template').html();
    var mentionDateLineTemplate = $informationSec.find('#mention-dateline-template').html();
    var $title = $informationSec.find(".title");
    var $contentArea = $informationSec.find('.content_area');

    var params = {
      "emplId": myPref.emplId
    };

    restResourse.chat.getMentionList(params, function(data) {
      if (data) {
        var messages = [];
        $.each(data, function(idx, row) {
          var sender = catalogSection.getUserObj(row.spkrId);
          var channel = catalogSection.getChannelObj(row.peer2);
          var message = {
            "msgId": row.chatId,
            "img": "../img/profile_img" + row.spkrId + ".jpg",
            "imgAlt": sender.loginId,
            "channel": channel ? channel.name : "unknown",
            "sender": sender.loginId,
            "msgText": row.msg,
            "date": new Date(row.creTime).format("yyyy/MM/dd"),
            "time": new Date(row.creTime).format("a hh mm")
          };

          messages.push(message);
        });

        $contentArea.empty();
        $title.html("Mention #" + myPref.loginId);
        for (var key = 0; key < messages.length; key++) {
          if(key === 0) {
            $contentArea.append(Mustache.render(mentionDateLineTemplate, {"date" : messages[key].date}));
          }
          if(messages[key - 1] && messages[key - 1].date != messages[key].date) {
            $contentArea.append(Mustache.render(mentionDateLineTemplate, {"date" : messages[key].date}));
          }
          $contentArea.append(Mustache.render(mentionTemplate, messages[key]));
        }
      }
    });
    resizeInformationSection();
    _informationSectionScroll();
    $informationSec.show();
  }

  function displayMember(members) {
    var $contentArea = $informationSec.find('.content_area');
    for(var key in members) {
      var userValue = catalogSection.getUserObj(members[key]);
      var imgUrl = "../img/profile_img" + userValue.emplId + ".jpg";
      $contentArea.find(".members").append("
" + userValue.loginId + "
");
    }
  }

  function hideMember(member) {
    var $contentArea = $informationSec.find('.content_area');
    $contentArea.find(".members [data-emplid='" + member + "']").remove();
  }

  function hideSection() {
    $informationSec.hide();
  }

  function showSection() {
    $informationSec.show();
  }

  function _informationSectionScroll() {
    $informationSec.find(".ibox-content").mCustomScrollbar({
      axis:"y",
  		setWidth: "auto",
      theme:"3d"
    });
  }

  return {
    initAsideSection: initAsideSection,
    resizeInformationSection: resizeInformationSection,
    showAboutChannel: showAboutChannel,
    showAboutUser: showAboutUser,
    adjustAsideArea: adjustAsideArea,
    displayMember: displayMember,
    showMentionList: showMentionList,
    hideMember: hideMember,
    hideSection: hideSection,
    showSection: showSection
  };
})();

module.exports = informationSection;
<|endoftext|>


<commit_before>/*jslint devel:true, node:true, nomen:true */
// depends: editor.js

(function (editor) {
	"use strict";

	function $(id) {
		return document.getElementById(id);
	}

	function createInfoLink(str, isURL, isCase) {
		if (isURL) {
			return "
" + str + "
";
		} else if (isCase) {
			if (str.length > 0 && str[str.length - 1] !== '/') {
				return "
" + str + "
";
			} else {
				return "
" + str + "
";
			}
		} else {
			return "
" + str + "
";
		}
	}

	function showFile(file) {
		editor.setFileName(file);
		console.log("showFile:" + file);
		editor.socket.emit('reqOpenFile', file);
	}

	function backToInfo() {
		$('info_back_button_area').style.display = "none";
		editor.socket.emit('reqUpdateInformation');
	}

	editor.socket.on('updateInformation', function (pmdStr, cmdStr) {
		var pmdData = JSON.parse(pmdStr),
			cmdData = JSON.parse(cmdStr),
			elem,
			elemKdb,
			i;
		//console.log("PMDDATA", pmdData);
		//console.log("CMDDATA", cmdData);
		$('info_text_area').style.display = "block";
		$('info_opened_text_area').style.display = "none";
		if (pmdData) {
			if (pmdData.hasOwnProperty("hpcpf")) {
				elem = pmdData.hpcpf;
				if (elem.hasOwnProperty('project_meta_data')) {
					elem = elem.project_meta_data;
					if (elem.hasOwnProperty("name_hr")) {
						editor.setProjectName(elem.name_hr); // editor.js
					}
					if (elem.hasOwnProperty("description_hr")) {
						$('info_description').innerHTML = elem.description_hr;
					}
					/*
					if (elem.hasOwnProperty("workflow")) {
						$('info_workflow').innerHTML = "";
						for (i = 0; i < elem.workflow.length; i = i + 1) {
							$('info_workflow').innerHTML += createInfoLink(elem.workflow[i], false);
						}
					}
					if (elem.hasOwnProperty("case")) {
						$('info_case').innerHTML = "";
						for (i = 0; i < elem["case"].length; i = i + 1) {
							$('info_case').innerHTML += createInfoLink(elem["case"][i], false, true);
						}
					}
					if (elem.hasOwnProperty("kdb")) {
						elemKdb = elem.kdb;
						if (elemKdb.hasOwnProperty("base")) {
							$('info_kdb_url').innerHTML = createInfoLink(elemKdb.base, true);
						}
						if (elemKdb.hasOwnProperty("changed")) {
							$('info_kdb_change').innerHTML = elemKdb.changed.toString();
						}
						if (elemKdb.hasOwnProperty("details_of_changes")) {
							$('info_kdb_detail_of_change').innerHTML = elemKdb.details_of_changes;
						}
					}
					if (elem.hasOwnProperty("log")) {
						if (elem.log.hasOwnProperty("conf")) {
							$('info_log').innerHTML = createInfoLink(elem.log.conf, false);
						}
					}
					*/
				}
			}
		}
		$('info_case').innerHTML = "";
		for (i = 0; i < cmdData.length; i = i + 1) {
			if (cmdData[i].hasOwnProperty('name_hr')) {
				$('info_case').innerHTML += createInfoLink(cmdData[i].varname, false, true);
			}
		}
	});

	editor.socket.on('openFile', function (data) {
		$('info_back_button_area').style.display = "block";
		$('info_text_area').style.display = "none";
		$('info_opened_text_area').style.display = "block";
		$('info_opened_text_area').innerHTML =
			"
"
			+ data
			+ "
";
		console.log($('info_opened_text_area').innerHTML);
	});

	/*
	function convertJSONtoTable(parentKey, json) {
		var key,
			result = "";
		for (key in json) {
			if (json.hasOwnProperty(key)) {
				if (typeof json[key] === 'object') {
					if (parentKey) {
						result += convertJSONtoTable(parentKey + " - " + key, json[key]);
					} else {
						result += convertJSONtoTable(key, json[key]);
					}
				} else {
					result += "
";
					result += "
";
					if (parentKey) {
						result += parentKey + " - ";
					}
					result += key;
					result += "
";
					result += "
";
					result += json[key];
					result += "
";
					result += "
";
				}
			}
		}
		return result;
	}
	*/

	function makeItemNode(name, text, top) {
		var itemRow = document.createElement('div'),
			nameProp = document.createElement('div'),
			textProp = document.createElement('div'),
			str_rowclass = 'row',
			str_nameclass = 'json_title',
			str_constclass = 'json_text',
			str_nameclass_top = 'json_title_top',
			str_constclass_top = 'json_text_top';

		itemRow.classList.add(str_rowclass);
		nameProp.innerHTML = name;
		textProp.innerHTML = text;
		nameProp.classList.add(str_nameclass);
		textProp.classList.add(str_constclass);
		if (top) {
			nameProp.classList.add(str_nameclass_top);
			itemRow.appendChild(nameProp);
		} else {
			itemRow.appendChild(nameProp);
			itemRow.appendChild(textProp);
		}
		return itemRow;
	}

	function makePropertyInputRow(type, key, val, inputNode, targetMachineList) {
		return [makeItemNode(key, val)];
	}

	function makePropertyOutputRow(type, key, val, inputNode, targetMachineList) {
		return [makeItemNode(key, val)];
	}

	function convertJSONtoTable(json) {
		var i,
			k,
			key,
			value,
			iokey,
			iokey2,
			ioval,
			ioval2,
			propertyRows,
			inputtype,
			outputtype,
			property = document.getElementById('info_opened_text_area');

		json = json.hpcpf.case_meta_data;
		for (key in json) {
			if (json.hasOwnProperty(key)) {
				if (key === 'inputs') {
					value = json[key];
					console.log(key, value);

					for (iokey in value) {
						if (value.hasOwnProperty(iokey)) {
							property.appendChild(makeItemNode('Input', "", true));

							ioval = value[iokey];
							if (ioval.hasOwnProperty('type')) {
								inputtype = ioval.type;
							}
							if (inputtype === 'target_machine' && !ioval.hasOwnProperty('machine')) {
								ioval.machine = "";
							}
							if (inputtype === 'target_machine' && !ioval.hasOwnProperty('cores')) {
								ioval.cores = 1;
							}
							if (inputtype === 'target_machine' && !ioval.hasOwnProperty('nodes')) {
								ioval.nodes = 1;
							}
							for (iokey2 in ioval) {
								if (ioval.hasOwnProperty(iokey2)) {
									if (ioval.hasOwnProperty(iokey2)) {
										ioval2 = ioval[iokey2];
										propertyRows = makePropertyInputRow(inputtype, iokey2, ioval2, ioval);
										for (i = 0; i < propertyRows.length; i = i + 1) {
											property.appendChild(propertyRows[i]);
										}
									}
								}
							}
						}
					}
				} else if (key === 'outputs') {
					value = json[key];
					for (iokey in value) {
						if (value.hasOwnProperty(iokey)) {
							property.appendChild(makeItemNode('Output', "", true));
							ioval = value[iokey];
							if (ioval.hasOwnProperty('type')) {
								outputtype = ioval.type;
							}
							for (iokey2 in ioval) {
								if (ioval.hasOwnProperty(iokey2)) {
									if (ioval.hasOwnProperty(iokey2)) {
										ioval2 = ioval[iokey2];
										propertyRows = makePropertyOutputRow(outputtype, iokey2, ioval2, ioval);
										for (i = 0; i < propertyRows.length; i = i + 1) {
											property.appendChild(propertyRows[i]);
										}
									}
								}
							}
						}
					}
				}
			}
		}
	}

	editor.socket.on('openJSON', function (data) {
		var textArea = $('info_opened_text_area'),
			json;
		$('info_back_button_area').style.display = "block";
		$('info_text_area').style.display = "none";
		$('info_opened_text_area').style.display = "block";
		try {
			json = JSON.parse(data);
			textArea.innerHTML = "";
			convertJSONtoTable(json);
		} catch (e) {
			textArea.innerHTML +=
				"
JSON Parse Error:" + e + "
"
				+ "
"
				+ data
				+ "
";
		}
		//console.log(json);
		//$('info_opened_text_area').innerHTML = "
"+data+"
";
	});

	editor.socket.on('connect', function () {
		editor.socket.emit('reqUpdateInformation');
	});

	window.editor_info_view = {};
	window.editor_info_view.showFile = showFile;
	window.editor_info_view.backToInfo = backToInfo;
}(window.editor));

<commit_msg>fix info page<commit_after>/*jslint devel:true, node:true, nomen:true */
// depends: editor.js

(function (editor) {
	"use strict";

	function $(id) {
		return document.getElementById(id);
	}

	function createInfoLink(str, isURL, isCase) {
		if (isURL) {
			return "
" + str + "
";
		} else if (isCase) {
			if (str.length > 0 && str[str.length - 1] !== '/') {
				return "
" + str + "
";
			} else {
				return "
" + str + "
";
			}
		} else {
			return "
" + str + "
";
		}
	}

	function showFile(file) {
		editor.setFileName(file);
		console.log("showFile:" + file);
		editor.socket.emit('reqOpenFile', file);
	}

	function backToInfo() {
		$('info_back_button_area').style.display = "none";
		editor.socket.emit('reqUpdateInformation');
	}

	editor.socket.on('updateInformation', function (pmdStr, cmdStr) {
		var pmdData = JSON.parse(pmdStr),
			cmdData = JSON.parse(cmdStr),
			elem,
			elemKdb,
			i;
		//console.log("PMDDATA", pmdData);
		//console.log("CMDDATA", cmdData);
		$('info_text_area').style.display = "block";
		$('info_opened_text_area').style.display = "none";
		if (pmdData) {
			if (pmdData.hasOwnProperty("hpcpf")) {
				elem = pmdData.hpcpf;
				if (elem.hasOwnProperty('project_meta_data')) {
					elem = elem.project_meta_data;
					if (elem.hasOwnProperty("name_hr")) {
						editor.setProjectName(elem.name_hr); // editor.js
					}
					if (elem.hasOwnProperty("description_hr")) {
						$('info_description').innerHTML = elem.description_hr;
					}
					/*
					if (elem.hasOwnProperty("workflow")) {
						$('info_workflow').innerHTML = "";
						for (i = 0; i < elem.workflow.length; i = i + 1) {
							$('info_workflow').innerHTML += createInfoLink(elem.workflow[i], false);
						}
					}
					if (elem.hasOwnProperty("case")) {
						$('info_case').innerHTML = "";
						for (i = 0; i < elem["case"].length; i = i + 1) {
							$('info_case').innerHTML += createInfoLink(elem["case"][i], false, true);
						}
					}
					if (elem.hasOwnProperty("kdb")) {
						elemKdb = elem.kdb;
						if (elemKdb.hasOwnProperty("base")) {
							$('info_kdb_url').innerHTML = createInfoLink(elemKdb.base, true);
						}
						if (elemKdb.hasOwnProperty("changed")) {
							$('info_kdb_change').innerHTML = elemKdb.changed.toString();
						}
						if (elemKdb.hasOwnProperty("details_of_changes")) {
							$('info_kdb_detail_of_change').innerHTML = elemKdb.details_of_changes;
						}
					}
					if (elem.hasOwnProperty("log")) {
						if (elem.log.hasOwnProperty("conf")) {
							$('info_log').innerHTML = createInfoLink(elem.log.conf, false);
						}
					}
					*/
				}
			}
		}
		$('info_case').innerHTML = "";
		for (i = 0; i < cmdData.length; i = i + 1) {
			if (cmdData[i].hasOwnProperty('name_hr')) {
				$('info_case').innerHTML += createInfoLink(cmdData[i].varname, false, true);
			}
		}
	});

	editor.socket.on('openFile', function (data) {
		$('info_back_button_area').style.display = "block";
		$('info_text_area').style.display = "none";
		$('info_opened_text_area').style.display = "block";
		$('info_opened_text_area').innerHTML =
			"
"
			+ data
			+ "
";
		console.log($('info_opened_text_area').innerHTML);
	});

	/*
	function convertJSONtoTable(parentKey, json) {
		var key,
			result = "";
		for (key in json) {
			if (json.hasOwnProperty(key)) {
				if (typeof json[key] === 'object') {
					if (parentKey) {
						result += convertJSONtoTable(parentKey + " - " + key, json[key]);
					} else {
						result += convertJSONtoTable(key, json[key]);
					}
				} else {
					result += "
";
					result += "
";
					if (parentKey) {
						result += parentKey + " - ";
					}
					result += key;
					result += "
";
					result += "
";
					result += json[key];
					result += "
";
					result += "
";
				}
			}
		}
		return result;
	}
	*/

	function makeItemNode(name, text, top) {
		var itemRow = document.createElement('div'),
			nameProp = document.createElement('div'),
			textProp = document.createElement('div'),
			str_rowclass = 'row',
			str_nameclass = 'json_title',
			str_constclass = 'json_text',
			str_nameclass_top = 'json_title_top',
			str_constclass_top = 'json_text_top';

		itemRow.classList.add(str_rowclass);
		nameProp.innerHTML = name;
		textProp.innerHTML = text;
		nameProp.classList.add(str_nameclass);
		textProp.classList.add(str_constclass);
		if (top) {
			nameProp.classList.add(str_nameclass_top);
			itemRow.appendChild(nameProp);
		} else {
			itemRow.appendChild(nameProp);
			itemRow.appendChild(textProp);
		}
		return itemRow;
	}

	function makePropertyInputRow(type, key, val, inputNode, targetMachineList) {
		return [makeItemNode(key, val)];
	}

	function makePropertyOutputRow(type, key, val, inputNode, targetMachineList) {
		return [makeItemNode(key, val)];
	}

	function convertJSONtoTable(json) {
		var i,
			k,
			key,
			value,
			iokey,
			iokey2,
			ioval,
			ioval2,
			propertyRows,
			type,
			property = document.getElementById('info_opened_text_area');

		json = json.hpcpf.case_meta_data;
		for (key in json) {
			if (json.hasOwnProperty(key)) {
				if (key === 'inputs' || key === 'outputs' || key === 'polling_files' || key === 'clean' || key === 'collection_files' || key === 'softwares') {
					value = json[key];

					for (iokey in value) {
						if (value.hasOwnProperty(iokey)) {
							if (key === "inputs") {
								property.appendChild(makeItemNode('Input', "", true));
							} else if (key === "outputs") {
								property.appendChild(makeItemNode('Output', "", true));
							} else if (key === "polling_files") {
								property.appendChild(makeItemNode('PollingFile', "", true));
							} else if (key === "clean") {
								property.appendChild(makeItemNode('Clean', "", true));
							} else if (key === "collection_files") {
								property.appendChild(makeItemNode('CollectionFile', "", true));
							} else if (key === "softwares") {
								property.appendChild(makeItemNode('Software', "", true));
							}

							ioval = value[iokey];
							type = "";
							if (ioval.hasOwnProperty('type')) {
								type = ioval.type;
							}
							for (iokey2 in ioval) {
								if (ioval.hasOwnProperty(iokey2)) {
									if (ioval.hasOwnProperty(iokey2)) {
										ioval2 = ioval[iokey2];
										propertyRows = makePropertyInputRow(type, iokey2, ioval2, ioval);
										for (i = 0; i < propertyRows.length; i = i + 1) {
											property.appendChild(propertyRows[i]);
										}
									}
								}
							}
						}
					}
				} else {
					propertyRows = makePropertyInputRow("", key, json[key]);
					for (i = 0; i < propertyRows.length; i = i + 1) {
						property.appendChild(propertyRows[i]);
					}
				}
			}
		}
	}

	editor.socket.on('openJSON', function (data) {
		var textArea = $('info_opened_text_area'),
			json;
		$('info_back_button_area').style.display = "block";
		$('info_text_area').style.display = "none";
		$('info_opened_text_area').style.display = "block";
		try {
			json = JSON.parse(data);
			textArea.innerHTML = "";
			convertJSONtoTable(json);
		} catch (e) {
			textArea.innerHTML +=
				"
JSON Parse Error:" + e + "
"
				+ "
"
				+ data
				+ "
";
		}
		//console.log(json);
		//$('info_opened_text_area').innerHTML = "
"+data+"
";
	});

	editor.socket.on('connect', function () {
		editor.socket.emit('reqUpdateInformation');
	});

	window.editor_info_view = {};
	window.editor_info_view.showFile = showFile;
	window.editor_info_view.backToInfo = backToInfo;
}(window.editor));

<|endoftext|>


<commit_before>class teresa extends Chara{
	static getText(){
		//キャラ説明
		return "サポートタイプ：
チームの回復が得意。";
	}
	constructor(aX,aY,aTeam,aOperationNum){
		let tData=teresa.getCharaData();
		super(aX,aY,aTeam,tData,aOperationNum);
		this.data=tData;
		this.MP=10;
	}
	static getCharaNatureSkill(){
		//特性の説明
		return "MPが10溜まった状態でゲームが始まる。ターン開始時HPが満タンかどうかで服装と性能が変化する。";
	}
	static getCharaData(){
		return {NAME:"テレサ",
						HP:80,
						MP:15,
						ATK:20,
						DEF:27,
						SPD:25,
						MOV:2,
						TYPE:"club",
						IMAGE:1098010001,
						DECK:teresa.getDeck(),
						CHANGE:1
		}
	}
	static getDeck(){
		return [
			{NUMBER:101,
				TEXT:"隣のマスに威力５のダメージ",
				RANGE:[["distance",1]],
				POWER:5,
				DELAY:0,
				MAGIC:0,
				SUPPORT_Be_Myself:[],
				SUPPORT_Af_Myself:[],
				SUPPORT_Be_Enemy:[],
				SUPPORT_Af_Enemy:[],
				SUPPORT_Otherwise:[],
				M_ATTACK:0,
				F_ATTACK:false,
		    E_ATTACK:true,
				ANIMATION:[4]
			},
			{NUMBER:102,
				TEXT:"２マス隣に威力４のダメージ",
				RANGE:[["distance",2]],
				POWER:4,
				DELAY:0,
				MAGIC:0,
				SUPPORT_Be_Myself:[],
				SUPPORT_Af_Myself:[],
				SUPPORT_Be_Enemy:[],
				SUPPORT_Af_Enemy:[],
				SUPPORT_Otherwise:[],
				M_ATTACK:0,
				F_ATTACK:false,
		    E_ATTACK:true,
				ANIMATION:[0]
			},
			{NUMBER:103,
				TEXT:"３マス隣に威力４のダメージ",
				RANGE:[["distance",3]],
				POWER:4,
				DELAY:0,
				MAGIC:0,
				SUPPORT_Be_Myself:[],
				SUPPORT_Af_Myself:[],
				SUPPORT_Be_Enemy:[],
				SUPPORT_Af_Enemy:[],
				SUPPORT_Otherwise:[],
				M_ATTACK:0,
				F_ATTACK:false,
		    E_ATTACK:true,
				ANIMATION:[0]
			},
			{NUMBER:104,
				TEXT:"縦一列に威力３のダメージ",
				RANGE:[["vertical",1]],
				POWER:3,
				DELAY:0,
				MAGIC:0,
				SUPPORT_Be_Myself:[],
				SUPPORT_Af_Myself:[],
				SUPPORT_Be_Enemy:[],
				SUPPORT_Af_Enemy:[],
				SUPPORT_Otherwise:[],
				M_ATTACK:0,
				F_ATTACK:false,
		    E_ATTACK:true,
				ANIMATION:[0]
			},
			{NUMBER:105,
				TEXT:"横一列に威力３ダメージ",
				RANGE:[["horizontal",1]],
				POWER:3,
				DELAY:0,
				MAGIC:0,
				SUPPORT_Be_Myself:[],
				SUPPORT_Af_Myself:[],
				SUPPORT_Be_Enemy:[],
				SUPPORT_Af_Enemy:[],
				SUPPORT_Otherwise:[],
				M_ATTACK:0,
				F_ATTACK:false,
		    E_ATTACK:true,
				ANIMATION:[0]
			},
			{NUMBER:106,
				TEXT:"十字に威力２ダメージ",
				RANGE:[["vertical",1],["horizontal",1]],
				POWER:2,
				DELAY:0,
				MAGIC:0,
				SUPPORT_Be_Myself:[],
				SUPPORT_Af_Myself:[],
				SUPPORT_Be_Enemy:[],
				SUPPORT_Af_Enemy:[],
				SUPPORT_Otherwise:[],
				M_ATTACK:0,
				F_ATTACK:false,
		    E_ATTACK:true,
				ANIMATION:[0]
			},
			{NUMBER:7,
				TEXT:"シャッフルしてもう一度行動",
				RANGE:[],
				POWER:0,
				DELAY:0,
				MAGIC:1,
				SUPPORT_Be_Myself:[],
				SUPPORT_Af_Myself:[{effect:"getTurn"}],
				SUPPORT_Be_Enemy:[],
				SUPPORT_Af_Enemy:[],
				SUPPORT_Otherwise:[{effect:"shuffle"}],
				M_ATTACK:0,
				F_ATTACK:false,
				E_ATTACK:true,
				ANIMATION:[0]
			},
			{NUMBER:108,
				TEXT:"相手全体に威力２のダメージ",
				RANGE:[["enemy"]],
				POWER:2,
				DELAY:10,
				MAGIC:0,
				SUPPORT_Be_Myself:[],
				SUPPORT_Af_Myself:[],
				SUPPORT_Be_Enemy:[],
				SUPPORT_Af_Enemy:[],
				SUPPORT_Otherwise:[],
				M_ATTACK:0,
				F_ATTACK:false,
		    E_ATTACK:true,
				ANIMATION:[5]
			},
			{NUMBER:109,
				TEXT:"周囲８マスに威力３のダメージ",
				RANGE:[["square",3]],
				POWER:3,
				DELAY:0,
				MAGIC:0,
				SUPPORT_Be_Myself:[],
				SUPPORT_Af_Myself:[],
				SUPPORT_Be_Enemy:[],
				SUPPORT_Af_Enemy:[],
				SUPPORT_Otherwise:[],
				M_ATTACK:0,
				F_ATTACK:false,
		    E_ATTACK:true,
				ANIMATION:[3]
			},
			{NUMBER:110,
				TEXT:"ランダムな８マスに味方が踏むと２０回復する地雷を設置",
				RANGE:[],
				POWER:0,
				DELAY:0,
				MAGIC:2,
				SUPPORT_Be_Myself:[],
				SUPPORT_Af_Myself:[{effect:"setTrap",trapEffect:"mine",value:-20,target:["enemy"],remove:true,range:[["random",10]]}],
				SUPPORT_Be_Enemy:[],
				SUPPORT_Af_Enemy:[],
				SUPPORT_Otherwise:[],
				M_ATTACK:0,
				F_ATTACK:true,
		    E_ATTACK:true,
				ANIMATION:[4,3]
			},
			{NUMBER:111,
				TEXT:"味方全体に威力４の回復",
				RANGE:[["ally"]],
				POWER:-4,
				DELAY:0,
				MAGIC:6,
				SUPPORT_Be_Myself:[],
				SUPPORT_Af_Myself:[],
				SUPPORT_Be_Enemy:[],
				SUPPORT_Af_Enemy:[],
				SUPPORT_Otherwise:[],
				M_ATTACK:-4,
				F_ATTACK:true,
		    E_ATTACK:false,
				ANIMATION:[7]
			},
			{NUMBER:112,
				TEXT:"自分に威力５の回復",
				RANGE:[],
				POWER:0,
				DELAY:0,
				MAGIC:3,
				SUPPORT_Be_Myself:[],
				SUPPORT_Af_Myself:[],
				SUPPORT_Be_Enemy:[],
				SUPPORT_Af_Enemy:[],
				SUPPORT_Otherwise:[],
				M_ATTACK:-5,
				F_ATTACK:false,
		    E_ATTACK:true,
				ANIMATION:[7]
			},
			{NUMBER:113,
				TEXT:"味方に威力３の回復",
				RANGE:[["ally"]],
				POWER:-3,
				DELAY:0,
				MAGIC:3,
				SUPPORT_Be_Myself:[],
				SUPPORT_Af_Myself:[],
				SUPPORT_Be_Enemy:[],
				SUPPORT_Af_Enemy:[],
				SUPPORT_Otherwise:[],
				M_ATTACK:0,
				F_ATTACK:true,
		    E_ATTACK:false,
				ANIMATION:[7]
			},
			{NUMBER:114,
				TEXT:"味方全体に威力４の回復 その後シャッフル",
				RANGE:[["enemy"]],
				POWER:-4,
				DELAY:0,
				MAGIC:0,
				SUPPORT_Be_Myself:[],
				SUPPORT_Af_Myself:[],
				SUPPORT_Be_Enemy:[],
				SUPPORT_Af_Enemy:[],
				SUPPORT_Otherwise:[{effect:"revers"},{effect:"shuffle"}],
				M_ATTACK:-4,
				F_ATTACK:true,
		    E_ATTACK:false,
				ANIMATION:[7]
			},
			{NUMBER:0,
					TEXT:"スカ　何も起こらない",
					RANGE:[],
					POWER:0,
					DELAY:0,
					MAGIC:0,
					SUPPORT_Be_Myself:[],
					SUPPORT_Af_Myself:[],
					SUPPORT_Be_Enemy:[],
					SUPPORT_Af_Enemy:[],
					SUPPORT_Otherwise:[{effect:"revers"}],
					M_ATTACK:0,
					F_ATTACK:false,
			    E_ATTACK:true,
					ANIMATION:[0]
				},]
	}	//ターン開始時
	startTurn(){
		return new Promise((res,rej)=>{
			//mp回復
			this.useMp(-1);
			//getTurnFlag
			this.additionalTurnFlag=this.getTurnFlag;
			this.getTurnFlag=false;
			res();
		})
	}
}
<commit_msg>テレサ追加<commit_after>class teresa extends Chara{
	static getText(){
		//キャラ説明
		return "サポートタイプ：
チームの回復が得意。";
	}
	constructor(aX,aY,aTeam,aOperationNum){
		let tData=teresa.getCharaData();
		super(aX,aY,aTeam,tData,aOperationNum);
		this.data=tData;
		this.MP=10;
	}
	static getCharaNatureSkill(){
		//特性の説明
		return "MPが10溜まった状態でゲームが始まる。ターン開始時HPが満タンかどうかで服装と性能が変化する。";
	}
	static getCharaData(){
		return {NAME:"テレサ",
						HP:80,
						MP:15,
						ATK:20,
						DEF:27,
						SPD:25,
						MOV:2,
						TYPE:"club",
						IMAGE:1098010001,
						DECK:teresa.getDeck(),
						CHANGE:1
		}
	}
	static getDeck(){
		return [
			{NUMBER:101,
				TEXT:"隣のマスに威力５のダメージ",
				RANGE:[["distance",1]],
				POWER:5,
				DELAY:0,
				MAGIC:0,
				SUPPORT_Be_Myself:[],
				SUPPORT_Af_Myself:[],
				SUPPORT_Be_Enemy:[],
				SUPPORT_Af_Enemy:[],
				SUPPORT_Otherwise:[],
				M_ATTACK:0,
				F_ATTACK:false,
		    E_ATTACK:true,
				ANIMATION:[4]
			},
			{NUMBER:102,
				TEXT:"２マス隣に威力４のダメージ",
				RANGE:[["distance",2]],
				POWER:4,
				DELAY:0,
				MAGIC:0,
				SUPPORT_Be_Myself:[],
				SUPPORT_Af_Myself:[],
				SUPPORT_Be_Enemy:[],
				SUPPORT_Af_Enemy:[],
				SUPPORT_Otherwise:[],
				M_ATTACK:0,
				F_ATTACK:false,
		    E_ATTACK:true,
				ANIMATION:[0]
			},
			{NUMBER:103,
				TEXT:"３マス隣に威力４のダメージ",
				RANGE:[["distance",3]],
				POWER:4,
				DELAY:0,
				MAGIC:0,
				SUPPORT_Be_Myself:[],
				SUPPORT_Af_Myself:[],
				SUPPORT_Be_Enemy:[],
				SUPPORT_Af_Enemy:[],
				SUPPORT_Otherwise:[],
				M_ATTACK:0,
				F_ATTACK:false,
		    E_ATTACK:true,
				ANIMATION:[0]
			},
			{NUMBER:104,
				TEXT:"縦一列に威力３のダメージ",
				RANGE:[["vertical",1]],
				POWER:3,
				DELAY:0,
				MAGIC:0,
				SUPPORT_Be_Myself:[],
				SUPPORT_Af_Myself:[],
				SUPPORT_Be_Enemy:[],
				SUPPORT_Af_Enemy:[],
				SUPPORT_Otherwise:[],
				M_ATTACK:0,
				F_ATTACK:false,
		    E_ATTACK:true,
				ANIMATION:[0]
			},
			{NUMBER:105,
				TEXT:"横一列に威力３ダメージ",
				RANGE:[["horizontal",1]],
				POWER:3,
				DELAY:0,
				MAGIC:0,
				SUPPORT_Be_Myself:[],
				SUPPORT_Af_Myself:[],
				SUPPORT_Be_Enemy:[],
				SUPPORT_Af_Enemy:[],
				SUPPORT_Otherwise:[],
				M_ATTACK:0,
				F_ATTACK:false,
		    E_ATTACK:true,
				ANIMATION:[0]
			},
			{NUMBER:106,
				TEXT:"自分に威力２の回復をしてDELAYを60下げる (タイプ一致時80)",
				RANGE:[],
				POWER:0,
				DELAY:0,
				MAGIC:5,
				SUPPORT_Be_Myself:[],
				SUPPORT_Af_Myself:[{effect:"delay",value:-60,additionOfMatchingType:-20}],
				SUPPORT_Be_Enemy:[],
				SUPPORT_Af_Enemy:[],
				SUPPORT_Otherwise:[],
				M_ATTACK:-2,
				F_ATTACK:false,
		    E_ATTACK:true,
				ANIMATION:[0]
			},
			{NUMBER:7,
				TEXT:"シャッフルしてもう一度行動",
				RANGE:[],
				POWER:0,
				DELAY:0,
				MAGIC:1,
				SUPPORT_Be_Myself:[],
				SUPPORT_Af_Myself:[{effect:"getTurn"}],
				SUPPORT_Be_Enemy:[],
				SUPPORT_Af_Enemy:[],
				SUPPORT_Otherwise:[{effect:"shuffle"}],
				M_ATTACK:0,
				F_ATTACK:false,
				E_ATTACK:true,
				ANIMATION:[0]
			},
			{NUMBER:108,
				TEXT:"相手全体に威力２の回復 その後MPを8回復(タイプ一致時10)",
				RANGE:[["enemy"]],
				POWER:-2,
				DELAY:0,
				MAGIC:0,
				SUPPORT_Be_Myself:[],
				SUPPORT_Af_Myself:[{effect:"mp",value:8,additionOfMatchingType:2}],
				SUPPORT_Be_Enemy:[],
				SUPPORT_Af_Enemy:[],
				SUPPORT_Otherwise:[],
				M_ATTACK:0,
				F_ATTACK:false,
		    E_ATTACK:true,
				ANIMATION:[5]
			},
			{NUMBER:109,
				TEXT:"キャラクター全体に敵味方無視の威力３の回復",
				RANGE:[["ally"],["enemy"]],
				POWER:-3,
				DELAY:0,
				MAGIC:2,
				SUPPORT_Be_Myself:[],
				SUPPORT_Af_Myself:[],
				SUPPORT_Be_Enemy:[],
				SUPPORT_Af_Enemy:[],
				SUPPORT_Otherwise:[],
				M_ATTACK:0,
				F_ATTACK:false,
		    E_ATTACK:true,
				ANIMATION:[7]
			},
			{NUMBER:110,
				TEXT:"ランダムな８マスに味方が踏むと２０回復する地雷を設置",
				RANGE:[],
				POWER:0,
				DELAY:0,
				MAGIC:2,
				SUPPORT_Be_Myself:[],
				SUPPORT_Af_Myself:[{effect:"setTrap",trapEffect:"mine",value:-20,target:["ally"],remove:true,range:[["random",8]]}],
				SUPPORT_Be_Enemy:[],
				SUPPORT_Af_Enemy:[],
				SUPPORT_Otherwise:[],
				M_ATTACK:0,
				F_ATTACK:true,
		    E_ATTACK:true,
				ANIMATION:[4,3]
			},
			{NUMBER:111,
				TEXT:"味方全体に威力４の回復",
				RANGE:[["ally"]],
				POWER:-4,
				DELAY:0,
				MAGIC:6,
				SUPPORT_Be_Myself:[],
				SUPPORT_Af_Myself:[],
				SUPPORT_Be_Enemy:[],
				SUPPORT_Af_Enemy:[],
				SUPPORT_Otherwise:[],
				M_ATTACK:-4,
				F_ATTACK:true,
		    E_ATTACK:false,
				ANIMATION:[7]
			},
			{NUMBER:112,
				TEXT:"自分に威力５の回復",
				RANGE:[],
				POWER:0,
				DELAY:0,
				MAGIC:3,
				SUPPORT_Be_Myself:[],
				SUPPORT_Af_Myself:[],
				SUPPORT_Be_Enemy:[],
				SUPPORT_Af_Enemy:[],
				SUPPORT_Otherwise:[],
				M_ATTACK:-5,
				F_ATTACK:false,
		    E_ATTACK:true,
				ANIMATION:[7]
			},
			{NUMBER:113,
				TEXT:"味方に威力３の回復",
				RANGE:[["ally"]],
				POWER:-3,
				DELAY:0,
				MAGIC:3,
				SUPPORT_Be_Myself:[],
				SUPPORT_Af_Myself:[],
				SUPPORT_Be_Enemy:[],
				SUPPORT_Af_Enemy:[],
				SUPPORT_Otherwise:[],
				M_ATTACK:0,
				F_ATTACK:true,
		    E_ATTACK:false,
				ANIMATION:[7]
			},
			{NUMBER:114,
				TEXT:"味方全体に威力４の回復 その後シャッフル",
				RANGE:[["enemy"]],
				POWER:-4,
				DELAY:0,
				MAGIC:0,
				SUPPORT_Be_Myself:[],
				SUPPORT_Af_Myself:[],
				SUPPORT_Be_Enemy:[],
				SUPPORT_Af_Enemy:[],
				SUPPORT_Otherwise:[{effect:"revers"},{effect:"shuffle"}],
				M_ATTACK:-4,
				F_ATTACK:true,
		    E_ATTACK:false,
				ANIMATION:[7]
			},
			{NUMBER:0,
					TEXT:"スカ　何も起こらない",
					RANGE:[],
					POWER:0,
					DELAY:0,
					MAGIC:0,
					SUPPORT_Be_Myself:[],
					SUPPORT_Af_Myself:[],
					SUPPORT_Be_Enemy:[],
					SUPPORT_Af_Enemy:[],
					SUPPORT_Otherwise:[{effect:"revers"}],
					M_ATTACK:0,
					F_ATTACK:false,
			    E_ATTACK:true,
					ANIMATION:[0]
				},]
	}	//ターン開始時
	startTurn(){
		return new Promise((res,rej)=>{

			//mp回復
			this.useMp(-1);
			//getTurnFlag
			this.additionalTurnFlag=this.getTurnFlag;
			this.getTurnFlag=false;

			console.log(this)
			console.log(this.image,1098010001)
			console.log(this.HP,this.originalHP)
			console.log(this.IMAGE==1098010001)
			console.log(this.HP==this.originalHP)
			if(this.image==1098010001&&this.HP==this.originalHP){
				console.log("in");
				attackAnimate(this,this,[7],()=>{
					freeLog(this,"服装","変化した");
				this.transform(this.getTransformData(1));
				res()})
			}
			else if(this.image==1098020001&&this.HP!=this.originalHP){
				console.log("in2");
				attackAnimate(this,this,[7],()=>{
					freeLog(this,"服装","元に戻った");
				this.transform(this.getTransformData(0));
				res()})
			}

				console.log("out");
			res();
		})
	}
	getTransformData(aNum){
		return teresa.getTransformData(aNum);
	}
	static getTransformData(aNum){
		let tData=[
			teresa.getCharaData(),
			{NAME:"テレサ",
							HP:100,
							MP:20,
							ATK:28,
							DEF:20,
							SPD:22,
							MOV:2,
							TYPE:"club",
							IMAGE:1098020001,
							DECK:teresa.getDeckTransform0(),
							CHANGE:0
			},
		]
		if(aNum==undefined) return tData;
		else return tData[aNum];
	}
	static getDeckTransform0(){
		return [
			{NUMBER:101,
				TEXT:"隣のマスに威力５のダメージ",
				RANGE:[["distance",1]],
				POWER:5,
				DELAY:0,
				MAGIC:0,
				SUPPORT_Be_Myself:[],
				SUPPORT_Af_Myself:[],
				SUPPORT_Be_Enemy:[],
				SUPPORT_Af_Enemy:[],
				SUPPORT_Otherwise:[],
				M_ATTACK:0,
				F_ATTACK:false,
		    E_ATTACK:true,
				ANIMATION:[4]
			},
			{NUMBER:102,
				TEXT:"２マス隣に威力４のダメージ",
				RANGE:[["distance",2]],
				POWER:4,
				DELAY:0,
				MAGIC:0,
				SUPPORT_Be_Myself:[],
				SUPPORT_Af_Myself:[],
				SUPPORT_Be_Enemy:[],
				SUPPORT_Af_Enemy:[],
				SUPPORT_Otherwise:[],
				M_ATTACK:0,
				F_ATTACK:false,
		    E_ATTACK:true,
				ANIMATION:[0]
			},
			{NUMBER:103,
				TEXT:"３マス隣に威力４のダメージ",
				RANGE:[["distance",3]],
				POWER:4,
				DELAY:0,
				MAGIC:0,
				SUPPORT_Be_Myself:[],
				SUPPORT_Af_Myself:[],
				SUPPORT_Be_Enemy:[],
				SUPPORT_Af_Enemy:[],
				SUPPORT_Otherwise:[],
				M_ATTACK:0,
				F_ATTACK:false,
		    E_ATTACK:true,
				ANIMATION:[0]
			},
			{NUMBER:104,
				TEXT:"縦一列に威力３のダメージ",
				RANGE:[["vertical",1]],
				POWER:3,
				DELAY:0,
				MAGIC:0,
				SUPPORT_Be_Myself:[],
				SUPPORT_Af_Myself:[],
				SUPPORT_Be_Enemy:[],
				SUPPORT_Af_Enemy:[],
				SUPPORT_Otherwise:[],
				M_ATTACK:0,
				F_ATTACK:false,
		    E_ATTACK:true,
				ANIMATION:[0]
			},
			{NUMBER:105,
				TEXT:"横一列に威力３ダメージ",
				RANGE:[["horizontal",1]],
				POWER:3,
				DELAY:0,
				MAGIC:0,
				SUPPORT_Be_Myself:[],
				SUPPORT_Af_Myself:[],
				SUPPORT_Be_Enemy:[],
				SUPPORT_Af_Enemy:[],
				SUPPORT_Otherwise:[],
				M_ATTACK:0,
				F_ATTACK:false,
		    E_ATTACK:true,
				ANIMATION:[0]
			},
			{NUMBER:106,
				TEXT:"３列の十字に威力２ダメージ",
				RANGE:[["vertical",2],["horizontal",2]],
				POWER:2,
				DELAY:0,
				MAGIC:0,
				SUPPORT_Be_Myself:[],
				SUPPORT_Af_Myself:[],
				SUPPORT_Be_Enemy:[],
				SUPPORT_Af_Enemy:[],
				SUPPORT_Otherwise:[],
				M_ATTACK:0,
				F_ATTACK:false,
		    E_ATTACK:true,
				ANIMATION:[0]
			},
			{NUMBER:7,
				TEXT:"シャッフルしてもう一度行動",
				RANGE:[],
				POWER:0,
				DELAY:0,
				MAGIC:1,
				SUPPORT_Be_Myself:[],
				SUPPORT_Af_Myself:[{effect:"getTurn"}],
				SUPPORT_Be_Enemy:[],
				SUPPORT_Af_Enemy:[],
				SUPPORT_Otherwise:[{effect:"shuffle"}],
				M_ATTACK:0,
				F_ATTACK:false,
				E_ATTACK:true,
				ANIMATION:[0]
			},
			{NUMBER:108,
				TEXT:"相手全体に威力２のダメージ",
				RANGE:[["enemy"]],
				POWER:2,
				DELAY:10,
				MAGIC:0,
				SUPPORT_Be_Myself:[],
				SUPPORT_Af_Myself:[],
				SUPPORT_Be_Enemy:[],
				SUPPORT_Af_Enemy:[],
				SUPPORT_Otherwise:[],
				M_ATTACK:0,
				F_ATTACK:false,
		    E_ATTACK:true,
				ANIMATION:[5]
			},
			{NUMBER:109,
				TEXT:"周囲８マスに威力３のダメージ",
				RANGE:[["square",3]],
				POWER:3,
				DELAY:0,
				MAGIC:0,
				SUPPORT_Be_Myself:[],
				SUPPORT_Af_Myself:[],
				SUPPORT_Be_Enemy:[],
				SUPPORT_Af_Enemy:[],
				SUPPORT_Otherwise:[],
				M_ATTACK:0,
				F_ATTACK:false,
		    E_ATTACK:true,
				ANIMATION:[3]
			},
			{NUMBER:110,
				TEXT:"ランダムな８マスに味方が踏むと２０回復する地雷を設置",
				RANGE:[],
				POWER:0,
				DELAY:0,
				MAGIC:2,
				SUPPORT_Be_Myself:[],
				SUPPORT_Af_Myself:[{effect:"setTrap",trapEffect:"mine",value:-20,target:["ally"],remove:true,range:[["random",8]]}],
				SUPPORT_Be_Enemy:[],
				SUPPORT_Af_Enemy:[],
				SUPPORT_Otherwise:[],
				M_ATTACK:0,
				F_ATTACK:true,
		    E_ATTACK:true,
				ANIMATION:[4,3]
			},
			{NUMBER:111,
				TEXT:"味方全体に威力４の回復",
				RANGE:[["ally"]],
				POWER:-4,
				DELAY:0,
				MAGIC:6,
				SUPPORT_Be_Myself:[],
				SUPPORT_Af_Myself:[],
				SUPPORT_Be_Enemy:[],
				SUPPORT_Af_Enemy:[],
				SUPPORT_Otherwise:[],
				M_ATTACK:-4,
				F_ATTACK:true,
		    E_ATTACK:false,
				ANIMATION:[7]
			},
			{NUMBER:112,
				TEXT:"２マス隣と３マス隣に威力４のダメージ",
				RANGE:[["distance",2],["distance",3]],
				POWER:4,
				DELAY:0,
				MAGIC:0,
				SUPPORT_Be_Myself:[],
				SUPPORT_Af_Myself:[],
				SUPPORT_Be_Enemy:[],
				SUPPORT_Af_Enemy:[],
				SUPPORT_Otherwise:[],
				M_ATTACK:0,
				F_ATTACK:false,
		    E_ATTACK:true,
				ANIMATION:[7]
			},
			{NUMBER:113,
				TEXT:"味方に威力３の回復",
				RANGE:[["ally"]],
				POWER:-3,
				DELAY:0,
				MAGIC:3,
				SUPPORT_Be_Myself:[],
				SUPPORT_Af_Myself:[],
				SUPPORT_Be_Enemy:[],
				SUPPORT_Af_Enemy:[],
				SUPPORT_Otherwise:[],
				M_ATTACK:0,
				F_ATTACK:true,
		    E_ATTACK:false,
				ANIMATION:[7]
			},
			{NUMBER:114,
				TEXT:"味方全体に威力４の回復 その後シャッフル",
				RANGE:[["enemy"]],
				POWER:-4,
				DELAY:0,
				MAGIC:0,
				SUPPORT_Be_Myself:[],
				SUPPORT_Af_Myself:[],
				SUPPORT_Be_Enemy:[],
				SUPPORT_Af_Enemy:[],
				SUPPORT_Otherwise:[{effect:"revers"},{effect:"shuffle"}],
				M_ATTACK:-4,
				F_ATTACK:true,
		    E_ATTACK:false,
				ANIMATION:[7]
			},
			{NUMBER:0,
					TEXT:"スカ　何も起こらない",
					RANGE:[],
					POWER:0,
					DELAY:0,
					MAGIC:0,
					SUPPORT_Be_Myself:[],
					SUPPORT_Af_Myself:[],
					SUPPORT_Be_Enemy:[],
					SUPPORT_Af_Enemy:[],
					SUPPORT_Otherwise:[{effect:"revers"}],
					M_ATTACK:0,
					F_ATTACK:false,
			    E_ATTACK:true,
					ANIMATION:[0]
				},]
	}
}
<|endoftext|>


<commit_before>/*global module:true*/
'use strict';

Math.log10 = Math.log10 || function(x) {
  return Math.log(x) / Math.LN10;
};

(function() {
  var Helpers = {
    avg: function(arr) {
      var v = 0;
      for (var index = 0; index < arr.length; ++index) {
        v += arr[index];
      }
      return v / arr.length;
    },
    min: function(arr) {
      if (arr.length === 0) return 0;
      var v = arr[0];
      for (var index = 1; index < arr.length; ++index) {
        var v2 = arr[index];
        if (Array.isArray(v2)) v2 = Helpers.avg(v2);
        if (v2 < v) v = v2;
      }
      return Math.max(0, v);
    },
    max: function(arr) {
      var v = 0;
      for (var index = 0; index < arr.length; ++index) {
        var v2 = arr[index];
        if (Array.isArray(v2)) v2 = Helpers.avg(v2);
        if (v2 > v) v = v2;
      }
      return Math.max(0, v);
    },
    upperMax: function(arr) {
      var v = 0;
      for (var index = 0; index < arr.length; ++index) {
        var v2 = arr[index];
        if (Array.isArray(v2)) v2 = Helpers.max(v2);
        if (v2 > v) v = v2;
      }
      return Math.max(0, v);
    },
    niceNumbers: function(range, round) {
      var exponent = Math.floor(Math.log10(range));
      var fraction = range / Math.pow(10, exponent);
      var niceFraction;
      if (round) {
        if (fraction < 1.5) niceFraction = 1;
        else if (fraction < 3) niceFraction = 2;
        else if (fraction < 7) niceFraction = 5;
        else niceFraction = 10;
      } else {
        if (fraction <= 1.0) niceFraction = 1;
        else if (fraction <= 2) niceFraction = 2;
        else if (fraction <= 5) niceFraction = 5;
        else niceFraction = 10;
      }
      return niceFraction * Math.pow(10, exponent);
    },
    getLinearTicks: function(min, max, maxTicks) {
      var range = Helpers.niceNumbers(max - min, false);
      var tickSpacing = Helpers.niceNumbers(range / (maxTicks - 1), true);
      return [
        Math.floor(min / tickSpacing) * tickSpacing,
        Math.ceil(max / tickSpacing) * tickSpacing,
        tickSpacing
      ];
    }
  };

  var BarChart = (function() {
    function BarChart(ctx, options) {
      this.options = {
        font: 'Helvetica',
        fontSize_title: 24,
        fontSize_axis: 20,
        fontSize_ticks: 18,
        fontSize_labels: 18,
        barPaddingPercent: 0.10,
        tickPaddingPercent: 0.10,
        padding_vertical: 10,
        padding_horizontal: 10,
        padding_ticks: 10,
        fillColor_background: 'rgb(220, 220, 220)',
        strokeColor_bar: 'rgb(0, 0, 0)',
        fillColor_bar: 'rgb(180, 180, 180)'
      };
      options = options || { };
      for (var key in this.options) {
        if (options.hasOwnProperty(key)) this.options[key] = options[key];
      }
      this.ctx = ctx;
      this.content = { };
    }

    BarChart.prototype.update = function(content) {
      if (typeof content !== 'object') {
        throw new Error('Collections must be objects.');
      } else if (!(content.hasOwnProperty('labels') && content.hasOwnProperty('data'))) {
        throw new Error('Collection must specify labels and data.');
      } else if (!(Array.isArray(content.labels) && Array.isArray(content.data))) {
        throw new Error('Labels and data must be arrays.');
      } else if (content.labels.length !== content.data.length) {
        throw new Error('Labels and data length must match.');
      }
      this.content = content;
      this.redraw();
    };

    BarChart.prototype.redraw = function() {
      setTimeout(function() {
        this._draw();
      }.bind(this), 0);
    };

    BarChart.prototype._draw = function() {
      var options = this.options;
      var ctx = this.ctx, content = this.content;
      ctx.translate(-0.5, -0.5);
      var width = ctx.canvas.width, height = ctx.canvas.height;
      var remainingWidth = width, remainingHeight = height;
      var index;

      if (options.fillColor_background != null) {
        ctx.save();
        ctx.fillStyle = options.fillColor_background;
        ctx.fillRect(0, 0, width, height);
        ctx.restore();
      }

      var topYPadding = options.padding_horizontal;
      remainingHeight -= options.padding_horizontal;
      ctx.fillStyle = 'rgb(0, 0, 0)';
      /* Draw title of bar chart */
      if (content.title != null) {
        ctx.save();
        ctx.font = options.fontSize_title + 'px ' + options.font;
        ctx.textAlign = 'center';
        ctx.fillText(content.title, width / 2, topYPadding + options.fontSize_title);
        ctx.restore();
        remainingHeight -= options.fontSize_title * 1.25;
        topYPadding += options.fontSize_title * 1.25;
      }

      /* Compute required left padding */
      var leftXPadding = options.padding_vertical;
      remainingWidth  -= options.padding_vertical;

      var leftXDrawYLabel = null;
      if (content.yAxis != null) {
        leftXDrawYLabel = leftXPadding + options.fontSize_axis * 0.5;
        remainingWidth -= options.fontSize_axis * 1.25;
        leftXPadding += options.fontSize_axis * 1.25;
      }

      ctx.save();
      ctx.font = options.fontSize_ticks + 'px ' + options.font;
      var maxChartValue = Helpers.upperMax(content.data);
      var maxYAxisTickWidth = Math.ceil(ctx.measureText(Math.ceil(Math.max(maxChartValue, 100))).width) + options.padding_ticks;
      remainingWidth -= maxYAxisTickWidth;
      leftXPadding += maxYAxisTickWidth;
      ctx.restore();

      var rightXPadding = options.padding_vertical;
      remainingWidth -= options.padding_vertical;

      /* Draw x-axis label of bar chart */
      var bottomYPadding = options.padding_horizontal;
      remainingHeight -= options.padding_horizontal;
      if (content.xAxis != null) {
        ctx.save();
        ctx.font = options.fontSize_axis + 'px ' + options.font;
        ctx.fillStyle = 'rgb(0, 0, 0)';
        ctx.textAlign = 'center';
        ctx.fillText(content.xAxis, (width - remainingWidth) + remainingWidth / 2, height - bottomYPadding);
        remainingHeight -= options.fontSize_axis;
        bottomYPadding += options.fontSize_axis;
        ctx.restore();
      }

      /* Draw x-axis labels */
      ctx.save();
      ctx.textAlign = 'center';
      ctx.font = options.fontSize_labels + 'px ' + options.font;
      var widthPerBar = remainingWidth / content.data.length;
      var computedBarPadding = Math.floor((widthPerBar * options.barPaddingPercent) / 2);
      for (index = 0; index < content.labels.length; ++index) {
        ctx.fillText(
          content.labels[index],
          leftXPadding + index * widthPerBar + widthPerBar / 2,
          height - options.fontSize_labels / 2 - bottomYPadding
        );
      }
      remainingHeight -= options.fontSize_labels * 1.5;
      ctx.restore();

      /* Draw boundaries */
      ctx.save();
      ctx.strokeStyle = 'rgb(0, 0, 0)';
      ctx.beginPath();
      ctx.moveTo(leftXPadding, topYPadding);
      ctx.lineTo(leftXPadding, topYPadding + remainingHeight);
      ctx.lineTo(leftXPadding + remainingWidth, topYPadding + remainingHeight);
      ctx.stroke();
      ctx.restore();

      /* Draw y-axis label of bar chart */
      if (content.yAxis != null) {
        ctx.save();
        ctx.translate(0, 0);
        ctx.rotate(Math.PI * 1.5);
        ctx.font = options.fontSize_axis + 'px ' + options.font;
        ctx.fillStyle = 'rgb(0, 0, 0)';
        ctx.textAlign = 'center';
        ctx.fillText(content.yAxis, -(topYPadding + remainingHeight / 2), leftXDrawYLabel);
        ctx.restore();
      }

      /* Draw y-axis labels */
      ctx.save();
      ctx.font = options.fontSize_ticks + 'px ' + options.font;
      ctx.textAlign = 'right';
      var tickMeta = Helpers.getLinearTicks(0, maxChartValue, Math.max(2, remainingHeight / (options.fontSize_ticks * (1 + options.tickPaddingPercent))));
      maxChartValue = tickMeta[1] + Math.ceil(maxChartValue / options.fontSize_ticks);
      var ticks = [];
      while (tickMeta[0] <= tickMeta[1]) {
        ticks.push(tickMeta[0]);
        tickMeta[0] += tickMeta[2];
      }
      for (index = 0; index < ticks.length; ++index) {
        var tickHeight = Math.round(remainingHeight * (ticks[index] / maxChartValue));
        ctx.fillText(ticks[index] + '', leftXPadding - options.padding_ticks, topYPadding + remainingHeight - tickHeight);
      }
      ctx.restore();

      /* Draw bars */
      ctx.save();
      ctx.strokeStyle = options.strokeColor_bar;
      ctx.fillStyle = options.fillColor_bar;
      for (index = 0; index < content.data.length; ++index) {
        var v = content.data[index];
        if (Array.isArray(v)) v = Helpers.avg(v);
        var renderBarHeight = Math.round(remainingHeight * (v / maxChartValue));
        ctx.beginPath();
        ctx.moveTo(leftXPadding + widthPerBar * index + computedBarPadding, topYPadding + remainingHeight);
        ctx.lineTo(leftXPadding + widthPerBar * index + computedBarPadding, topYPadding + remainingHeight - renderBarHeight);
        ctx.lineTo(leftXPadding + widthPerBar * index + (widthPerBar - 1) - computedBarPadding, topYPadding + remainingHeight - renderBarHeight);
        ctx.lineTo(leftXPadding + widthPerBar * index + (widthPerBar - 1) - computedBarPadding, topYPadding + remainingHeight);
        ctx.stroke();
        ctx.fill();
      }
      ctx.restore();
    };

    return BarChart;
  })();

  if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
    module.exports = BarChart;
  } else {
    window.BarChart = BarChart;
  }
})();
<commit_msg>Add logarithmic scale support<commit_after>/*global module:true*/
'use strict';

Math.log2 = Math.log2 || function(x) {
  return Math.log(x) / Math.LN2;
};

Math.log10 = Math.log10 || function(x) {
  return Math.log(x) / Math.LN10;
};

(function() {
  var Helpers = {
    avg: function(arr) {
      var v = 0;
      for (var index = 0; index < arr.length; ++index) {
        v += arr[index];
      }
      return v / arr.length;
    },
    min: function(arr) {
      if (arr.length === 0) return 0;
      var v = arr[0];
      for (var index = 1; index < arr.length; ++index) {
        var v2 = arr[index];
        if (Array.isArray(v2)) v2 = Helpers.avg(v2);
        if (v2 < v) v = v2;
      }
      return Math.max(0, v);
    },
    max: function(arr) {
      var v = 0;
      for (var index = 0; index < arr.length; ++index) {
        var v2 = arr[index];
        if (Array.isArray(v2)) v2 = Helpers.avg(v2);
        if (v2 > v) v = v2;
      }
      return Math.max(0, v);
    },
    upperMax: function(arr) {
      var v = 0;
      for (var index = 0; index < arr.length; ++index) {
        var v2 = arr[index];
        if (Array.isArray(v2)) v2 = Helpers.max(v2);
        if (v2 > v) v = v2;
      }
      return Math.max(0, v);
    },
    niceNumbers: function(range, round) {
      var exponent = Math.floor(Math.log10(range));
      var fraction = range / Math.pow(10, exponent);
      var niceFraction;
      if (round) {
        if (fraction < 1.5) niceFraction = 1;
        else if (fraction < 3) niceFraction = 2;
        else if (fraction < 7) niceFraction = 5;
        else niceFraction = 10;
      } else {
        if (fraction <= 1.0) niceFraction = 1;
        else if (fraction <= 2) niceFraction = 2;
        else if (fraction <= 5) niceFraction = 5;
        else niceFraction = 10;
      }
      return niceFraction * Math.pow(10, exponent);
    },
    getLinearTicks: function(min, max, maxTicks) {
      var range = Helpers.niceNumbers(max - min, false);
      var tickSpacing = Helpers.niceNumbers(range / (maxTicks - 1), true);
      return [
        Math.floor(min / tickSpacing) * tickSpacing,
        Math.ceil(max / tickSpacing) * tickSpacing,
        tickSpacing
      ];
    }
  };

  var BarChart = (function() {
    function BarChart(ctx, options) {
      this.options = {
        font: 'Helvetica',
        fontSize_title: 24,
        fontSize_axis: 20,
        fontSize_ticks: 18,
        fontSize_labels: 18,
        barPaddingPercent: 0.10,
        tickPaddingPercent: 0.10,
        padding_vertical: 10,
        padding_horizontal: 10,
        padding_ticks: 10,
        fillColor_background: 'rgb(220, 220, 220)',
        strokeColor_bar: 'rgb(0, 0, 0)',
        fillColor_bar: 'rgb(180, 180, 180)',
        scaleStyle: 'linear'
      };
      options = options || { };
      for (var key in this.options) {
        if (options.hasOwnProperty(key)) this.options[key] = options[key];
      }
      this.ctx = ctx;
      this.content = { };
    }

    BarChart.prototype.update = function(content) {
      if (typeof content !== 'object') {
        throw new Error('Collections must be objects.');
      } else if (!(content.hasOwnProperty('labels') && content.hasOwnProperty('data'))) {
        throw new Error('Collection must specify labels and data.');
      } else if (!(Array.isArray(content.labels) && Array.isArray(content.data))) {
        throw new Error('Labels and data must be arrays.');
      } else if (content.labels.length !== content.data.length) {
        throw new Error('Labels and data length must match.');
      }
      if (this.options.scaleStyle === 'log2') {
        for (var i = 0; i < content.data.length; ++i) {
          if (Array.isArray(content.data[i])) {
            for (var i2 = 0; i2 < content.data[i].length; ++i2) content.data[i][i2] = Math.log2(content.data[i][i2]);
          } else content.data[i] = Math.log2(content.data[i]);
        }
      }
      this.content = content;
      this.redraw();
    };

    BarChart.prototype.redraw = function() {
      setTimeout(function() {
        this._draw();
      }.bind(this), 0);
    };

    BarChart.prototype._draw = function() {
      var options = this.options;
      var ctx = this.ctx, content = this.content;
      ctx.translate(-0.5, -0.5);
      var width = ctx.canvas.width, height = ctx.canvas.height;
      var remainingWidth = width, remainingHeight = height;
      var index;

      if (options.fillColor_background != null) {
        ctx.save();
        ctx.fillStyle = options.fillColor_background;
        ctx.fillRect(0, 0, width, height);
        ctx.restore();
      }

      var topYPadding = options.padding_horizontal;
      remainingHeight -= options.padding_horizontal;
      ctx.fillStyle = 'rgb(0, 0, 0)';
      /* Draw title of bar chart */
      if (content.title != null) {
        ctx.save();
        ctx.font = options.fontSize_title + 'px ' + options.font;
        ctx.textAlign = 'center';
        ctx.fillText(content.title, width / 2, topYPadding + options.fontSize_title);
        ctx.restore();
        remainingHeight -= options.fontSize_title * 1.25;
        topYPadding += options.fontSize_title * 1.25;
      }

      /* Compute required left padding */
      var leftXPadding = options.padding_vertical;
      remainingWidth  -= options.padding_vertical;

      var leftXDrawYLabel = null;
      if (content.yAxis != null) {
        leftXDrawYLabel = leftXPadding + options.fontSize_axis * 0.5;
        remainingWidth -= options.fontSize_axis * 1.25;
        leftXPadding += options.fontSize_axis * 1.25;
      }

      ctx.save();
      ctx.font = options.fontSize_ticks + 'px ' + options.font;
      var maxChartValue = Helpers.upperMax(content.data);
      var maxYAxisTickWidth = options.scaleStyle == 'log2' ? Math.ceil(Math.pow(2, maxChartValue)) : maxChartValue;
      maxYAxisTickWidth = ctx.measureText(Math.max(maxYAxisTickWidth, 100)).width;
      maxYAxisTickWidth = Math.ceil(maxYAxisTickWidth) + options.padding_ticks;
      remainingWidth -= maxYAxisTickWidth;
      leftXPadding += maxYAxisTickWidth;
      ctx.restore();

      var rightXPadding = options.padding_vertical;
      remainingWidth -= options.padding_vertical;

      /* Draw x-axis label of bar chart */
      var bottomYPadding = options.padding_horizontal;
      remainingHeight -= options.padding_horizontal;
      if (content.xAxis != null) {
        ctx.save();
        ctx.font = options.fontSize_axis + 'px ' + options.font;
        ctx.fillStyle = 'rgb(0, 0, 0)';
        ctx.textAlign = 'center';
        ctx.fillText(content.xAxis, (width - remainingWidth) + remainingWidth / 2, height - bottomYPadding);
        remainingHeight -= options.fontSize_axis;
        bottomYPadding += options.fontSize_axis;
        ctx.restore();
      }

      /* Draw x-axis labels */
      ctx.save();
      ctx.textAlign = 'center';
      ctx.font = options.fontSize_labels + 'px ' + options.font;
      var widthPerBar = remainingWidth / content.data.length;
      var computedBarPadding = Math.floor((widthPerBar * options.barPaddingPercent) / 2);
      for (index = 0; index < content.labels.length; ++index) {
        ctx.fillText(
          content.labels[index],
          leftXPadding + index * widthPerBar + widthPerBar / 2,
          height - options.fontSize_labels / 2 - bottomYPadding
        );
      }
      remainingHeight -= options.fontSize_labels * 1.5;
      ctx.restore();

      /* Draw boundaries */
      ctx.save();
      ctx.strokeStyle = 'rgb(0, 0, 0)';
      ctx.beginPath();
      ctx.moveTo(leftXPadding, topYPadding);
      ctx.lineTo(leftXPadding, topYPadding + remainingHeight);
      ctx.lineTo(leftXPadding + remainingWidth, topYPadding + remainingHeight);
      ctx.stroke();
      ctx.restore();

      /* Draw y-axis label of bar chart */
      if (content.yAxis != null) {
        ctx.save();
        ctx.translate(0, 0);
        ctx.rotate(Math.PI * 1.5);
        ctx.font = options.fontSize_axis + 'px ' + options.font;
        ctx.fillStyle = 'rgb(0, 0, 0)';
        ctx.textAlign = 'center';
        ctx.fillText(content.yAxis, -(topYPadding + remainingHeight / 2), leftXDrawYLabel);
        ctx.restore();
      }

      /* Draw y-axis labels */
      ctx.save();
      ctx.font = options.fontSize_ticks + 'px ' + options.font;
      ctx.textAlign = 'right';
      var tickMeta = Helpers.getLinearTicks(0, maxChartValue, Math.max(2, remainingHeight / (options.fontSize_ticks * (1 + options.tickPaddingPercent))));
      maxChartValue = tickMeta[1] + Math.ceil(maxChartValue / options.fontSize_ticks);
      var ticks = [];
      while (tickMeta[0] <= tickMeta[1]) {
        ticks.push(tickMeta[0]);
        tickMeta[0] += tickMeta[2];
      }
      for (index = 0; index < ticks.length; ++index) {
        var tickHeight = Math.round(remainingHeight * (ticks[index] / maxChartValue));
        if (options.scaleStyle == 'log2') ticks[index] = Math.round(Math.pow(2, ticks[index]));
        ctx.fillText(ticks[index] + '', leftXPadding - options.padding_ticks, topYPadding + remainingHeight - tickHeight);
      }
      ctx.restore();

      /* Draw bars */
      ctx.save();
      ctx.strokeStyle = options.strokeColor_bar;
      ctx.fillStyle = options.fillColor_bar;
      for (index = 0; index < content.data.length; ++index) {
        var v = content.data[index];
        if (Array.isArray(v)) v = Helpers.avg(v);
        var renderBarHeight = Math.round(remainingHeight * (v / maxChartValue));
        ctx.beginPath();
        ctx.moveTo(leftXPadding + widthPerBar * index + computedBarPadding, topYPadding + remainingHeight);
        ctx.lineTo(leftXPadding + widthPerBar * index + computedBarPadding, topYPadding + remainingHeight - renderBarHeight);
        ctx.lineTo(leftXPadding + widthPerBar * index + (widthPerBar - 1) - computedBarPadding, topYPadding + remainingHeight - renderBarHeight);
        ctx.lineTo(leftXPadding + widthPerBar * index + (widthPerBar - 1) - computedBarPadding, topYPadding + remainingHeight);
        ctx.stroke();
        ctx.fill();
      }
      ctx.restore();
    };

    return BarChart;
  })();

  if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
    module.exports = BarChart;
  } else {
    window.BarChart = BarChart;
  }
})();
<|endoftext|>