diff --git a/Bin/Config/Common/ModelParaDefinesNM_cn.dat b/Bin/Config/Common/ModelParaDefinesNM_cn.dat index 5c1b0318..f13a50c2 100644 --- a/Bin/Config/Common/ModelParaDefinesNM_cn.dat +++ b/Bin/Config/Common/ModelParaDefinesNM_cn.dat @@ -1 +1 @@ -77u/PD94bWwgcup_mpadmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4NCg0KPCEtLSoqKioqKioqKiwzyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiotLT4NCjwhLS0gICAg5pys5paH5qGj55qE55uu55qE5piv5bu656uLV1RBSeaVsOWAvOinoyhOTSnmqKHlnZfnmoTlj4LmlbDlrprkuYkgICAgICAgICAgICAgICAgLS0+DQo8IS0tICAgIOS7heWMheWQq1BFQknmsYLop6PlmajmiYDpnIDnmoTlgqjlsYLjgIHkupXlkozlh6DkvZXlr7nosaHlj4LmlbAgICAgICAgICAgICAgICAgICAtLT4NCjwhLS0gICAgRGF0ZTogMjAyNjA2MTUgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC0tPg0KPCEtLSoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiotLT4NCg0KPCEtLQ0KICAgIOWPguaVsOiMg+WbtO+8mlBFQknmsYLop6PlmajmiYDpnIDnmoTlgqjlsYLjgIHkupXlkozlh6DkvZXlr7nosaHlj4LmlbANCiAgICDlr7nlupQgSFhfTldUTV9NT0RFTF9JTlBVVCDnu5PmnoTkvZPlrZfmrrUNCiAgICDpgJrov4cgX3BhcmFIZWxwZXItPmxvYWRQYXJhRGVmaW5lcygpIOWKoOi9ve+8jHNLZXkg5qCH6K+G5Li6IHNfTm1fU2VyaWUNCi0tPg0KDQo8Um9vdD4NCg0KICA8UGFyYUdyb3VwIE5hbWU9IiIgQWxpYXM9IuaXtumXtOatpeiuvue9riI+DQogICAgPFBhcmFJdGVtIE5hbWU9Ik5NX1RpbWVHcm93dGhFeHBvbmVudCIgQWxpYXM9IuaXtumXtOWinumVv+aMh+aVsCIgVW5pdD0iIiAgRGVmYXVsdD0iMS4wNSIgICBNYXg9IjEwIiAgICBNaW49IjEiICAgICBEaWdpdD0iNiIgRGVzYz0idGltZSBncm93dGggZXhwb25lbnQiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9Ik5NX0R0TWluIiAgICAgICAgICAgICAgQWxpYXM9IuacgOWwj+aXtumXtOatpSIgICBVbml0PSJoIiBEZWZhdWx0PSIwLjAwMjUiIE1heD0iMWUrMzAiIE1pbj0iMWUtMTIiIERpZ2l0PSI2IiBEZXNjPSJtaW5pbXVtIHRpbWUgc3RlcCIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iTk1fRHRNYXgiICAgICAgICAgICAgICBBbGlhcz0i5pyA5aSn5pe26Ze05q2lIiAgIFVuaXQ9ImgiIERlZmF1bHQ9IjEyLjUiICAgTWF4PSIxZSszMCIgTWluPSIxZS0xMiIgRGlnaXQ9IjYiIERlc2M9Im1heGltdW0gdGltZSBzdGVwIiAvPg0KICA8L1BhcmFHcm91cD4NCg0KICA8UGFyYUdyb3VwIE5hbWU9IiIgQWxpYXM9IuWCqOWxguWPguaVsCI+DQogICAgPFBhcmFJdGVtIE5hbWU9ImgiICAgQWxpYXM9IuWCqOWxguWOmuW6piIgICAgICAgVW5pdD0ibSIgICAgIERlZmF1bHQ9IjEwIiAgICBNYXg9IjEwMDAwIiAgTWluPSIxZS0wNSIgIERpZ2l0PSI2IiAgRGVzYz0icmVzZXJ2b2lyIHRoaWNrbmVzcyIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iUGkiICBBbGlhcz0i5Yid5aeL5Y6L5YqbIiAgICAgICBVbml0PSJNUGEiICAgRGVmYXVsdD0iNDAiICAgIE1heD0iNTAwIiAgICBNaW49IjAuMSIgICAgRGlnaXQ9IjYiICBEZXNjPSJpbml0aWFsIGZvcm1hdGlvbiBwcmVzc3VyZSIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iSyIgICBBbGlhcz0i5riX6YCP546HIiAgICAgICAgIFVuaXQ9Im1EIiAgICBEZWZhdWx0PSIyNSIgICAgTWF4PSIxMDAwMCIgIE1pbj0iMCIgICAgICBEaWdpdD0iNiIgIERlc2M9InBlcm1lYWJpbGl0eSIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0icGhpIiBBbGlhcz0i5a2U6ZqZ5bqmIiAgICAgICAgIFVuaXQ9IiIgICAgICBEZWZhdWx0PSIwLjEiICAgTWF4PSIxIiAgICAgIE1pbj0iMWUtMDUiICBEaWdpdD0iNiIgIERlc2M9InBvcm9zaXR5IiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJCbyIgIEFsaWFzPSLmsrnkvZPnp6/ns7vmlbAiICAgICBVbml0PSIiICAgICAgRGVmYXVsdD0iMS4yIiAgIE1heD0iMTAiICAgICBNaW49IjFlLTA2IiAgRGlnaXQ9IjYiICBEZXNjPSJvaWwgZm9ybWF0aW9uIHZvbHVtZSBmYWN0b3IiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9Ik1pdW8iIEFsaWFzPSLmsrnnm7jpu4/luqYiICAgICAgVW5pdD0ibVBhLnMiIERlZmF1bHQ9IjAuNSIgICBNYXg9IjEwMDAwIiAgTWluPSIxZS0wNiIgIERpZ2l0PSI2IiAgRGVzYz0ib2lsIHZpc2Nvc2l0eSIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iQnciICBBbGlhcz0i5rC05L2T56ev57O75pWwIiAgICAgVW5pdD0iIiAgICAgIERlZmF1bHQ9IjEiICAgICBNYXg9IjEwIiAgICAgTWluPSIxZS0wNiIgIERpZ2l0PSI2IiAgRGVzYz0id2F0ZXIgZm9ybWF0aW9uIHZvbHVtZSBmYWN0b3IiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9Ik1pdXciIEFsaWFzPSLmsLTnm7jpu4/luqYiICAgICAgVW5pdD0ibVBhLnMiIERlZmF1bHQ9IjEiICAgICBNYXg9IjEwMDAwIiAgTWluPSIxZS0wNiIgIERpZ2l0PSI2IiAgRGVzYz0id2F0ZXIgdmlzY29zaXR5IiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJDdGkiIEFsaWFzPSLnu7zlkIjljovnvKnns7vmlbAiICAgVW5pdD0iMS9NUGEiIERlZmF1bHQ9IjAuMDAxIiBNYXg9IjEwIiAgICAgTWluPSIxZS0zMCIgIERpZ2l0PSIxMCIgU2NpZW50aWZpYz0iMSIgRGVzYz0idG90YWwgY29tcHJlc3NpYmlsaXR5IiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJDZiIgIEFsaWFzPSLlsqnnn7PljovnvKnns7vmlbAiICAgVW5pdD0iMS9NUGEiIERlZmF1bHQ9IjAuMDAwMSIgTWF4PSIxMCIgICAgTWluPSIxZS0zMCIgIERpZ2l0PSIxMCIgU2NpZW50aWZpYz0iMSIgRGVzYz0icm9jayBjb21wcmVzc2liaWxpdHkiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IlNvaSIgQWxpYXM9IuWIneWni+WQq+ayuemlseWSjOW6piIgVW5pdD0iIiAgICAgIERlZmF1bHQ9IjAuOCIgICBNYXg9IjEiICAgICAgTWluPSIwIiAgICAgIERpZ2l0PSI2IiAgRGVzYz0iaW5pdGlhbCBvaWwgc2F0dXJhdGlvbiIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iU2dpIiBBbGlhcz0i5Yid5aeL5ZCr5rCU6aWx5ZKM5bqmIiBVbml0PSIiICAgICAgRGVmYXVsdD0iMCIgICAgIE1heD0iMSIgICAgICBNaW49IjAiICAgICAgRGlnaXQ9IjYiICBEZXNjPSJpbml0aWFsIGdhcyBzYXR1cmF0aW9uIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJTd2kiIEFsaWFzPSLliJ3lp4vlkKvmsLTppbHlkozluqYiIFVuaXQ9IiIgICAgICBEZWZhdWx0PSIwLjIiICAgTWF4PSIxIiAgICAgIE1pbj0iMCIgICAgICBEaWdpdD0iNiIgIERlc2M9ImluaXRpYWwgd2F0ZXIgc2F0dXJhdGlvbiIgLz4NCiAgPC9QYXJhR3JvdXA+DQoNCiAgPFBhcmFHcm91cCBOYW1lPSIiIEFsaWFzPSLkupXlj4LmlbAiPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJXX1giICAgIEFsaWFzPSJY5Z2Q5qCHIiAgICAgICBVbml0PSJtIiAgICBEZWZhdWx0PSIwIiAgICAgTWF4PSIxMDAwMCIgIE1pbj0iLTEwMDAwIiBEaWdpdD0iNiIgIERlc2M9IndlbGwgWCBjb29yZGluYXRlIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJXX1kiICAgIEFsaWFzPSJZ5Z2Q5qCHIiAgICAgICBVbml0PSJtIiAgICBEZWZhdWx0PSIwIiAgICAgTWF4PSIxMDAwMCIgIE1pbj0iLTEwMDAwIiBEaWdpdD0iNiIgIERlc2M9IndlbGwgWSBjb29yZGluYXRlIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJXX1J3IiAgIEFsaWFzPSLkupXnrZLljYrlvoQiICAgIFVuaXQ9Im0iICAgIERlZmF1bHQ9IjAuMSIgICBNYXg9IjEwIiAgICAgTWluPSIwLjAwMSIgIERpZ2l0PSI2IiAgRGVzYz0id2VsbGJvcmUgcmFkaXVzIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJXX1NraW4iIEFsaWFzPSLooajnmq7ns7vmlbAiICAgIFVuaXQ9IiIgICAgIERlZmF1bHQ9IjAiICAgICBNYXg9IjEwMDAiICAgTWluPSItMTAwIiAgIERpZ2l0PSI2IiAgRGVzYz0ic2tpbiBmYWN0b3IiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IldfQyIgICAgQWxpYXM9IuS6leetkuWCqOmbhuezu+aVsCIgVW5pdD0ibV4zL01QYSIgRGVmYXVsdD0iMCIgTWF4PSIxMDAwIiAgIE1pbj0iMCIgICAgICBEaWdpdD0iNiIgIERlc2M9IndlbGxib3JlIHN0b3JhZ2UgY29lZmZpY2llbnQiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IldfQm90dG9taG9sZU1EIiAgICAgICBBbGlhcz0i5LqV5bqVTUQiICAgICAgIFVuaXQ9Im0iICAgIERlZmF1bHQ9IjYwMDAiIE1heD0iMTAwMDAwIiBNaW49IjAiICAgICBEaWdpdD0iNiIgRGVzYz0iYm90dG9taG9sZSBtZWFzdXJlZCBkZXB0aCIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iV19XZWxsTGVuZ3RoIiAgICAgICAgIEFsaWFzPSLkupXouqvplb/luqYiICAgICBVbml0PSJtIiAgICBEZWZhdWx0PSIyMDAiICBNYXg9IjEwMDAwIiAgTWluPSIxZS0wNSIgRGlnaXQ9IjYiIERlc2M9IndlbGxib3JlIGxlbmd0aCIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iV19QZXJmb3JhdGlvbk1kU3RhcnQiIEFsaWFzPSLlsITlrZTotbflp4tNRCIgICBVbml0PSJtIiAgICBEZWZhdWx0PSI2MDAwIiBNYXg9IjEwMDAwMCIgTWluPSIwIiAgICAgRGlnaXQ9IjYiIERlc2M9InBlcmZvcmF0aW9uIHN0YXJ0IG1lYXN1cmVkIGRlcHRoIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJXX1BlcmZvcmF0aW9uTWRFbmQiICAgQWxpYXM9IuWwhOWtlOe7k+adn01EIiAgIFVuaXQ9Im0iICAgIERlZmF1bHQ9IjYwMzAiIE1heD0iMTAwMDAwIiBNaW49IjAiICAgICBEaWdpdD0iNiIgRGVzYz0icGVyZm9yYXRpb24gZW5kIG1lYXN1cmVkIGRlcHRoIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJXX0RyYWluQW5nbGUiICAgICAgICAgQWxpYXM9IuaOkuawtOinkuW6piIgICAgIFVuaXQ9ImRlZyIgIERlZmF1bHQ9IjAiICAgIE1heD0iMzYwIiAgIE1pbj0iLTM2MCIgIERpZ2l0PSI2IiBEZXNjPSJob3Jpem9udGFsIHdlbGwgZHJhaW4gYW5nbGUiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IldfTnVtYmVyT2ZGcmFjdHVyZXMiICBBbGlhcz0i6KOC57yd5pWw6YePIiAgICAgVW5pdD0iIiAgICAgRGVmYXVsdD0iMTUiICAgTWF4PSIxMDAwIiAgTWluPSIyIiAgICAgRGlnaXQ9IjAiIERlc2M9Im51bWJlciBvZiBmcmFjdHVyZXMiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IldfRnJhY3R1cmVIYWxmTGVuZ3RoIiBBbGlhcz0i6KOC57yd5Y2K6ZW/IiAgICAgVW5pdD0ibSIgICAgRGVmYXVsdD0iNTAiICAgTWF4PSIxMDAwMCIgTWluPSIxZS0wNSIgRGlnaXQ9IjYiIERlc2M9ImZyYWN0dXJlIGhhbGYtbGVuZ3RoIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJXX0ZyYWN0dXJlQW5nbGUiICAgICAgQWxpYXM9Iuijgue8neinkuW6piIgICAgIFVuaXQ9ImRlZyIgIERlZmF1bHQ9IjkwIiAgIE1heD0iMzYwIiAgIE1pbj0iLTM2MCIgIERpZ2l0PSI2IiBEZXNjPSJmcmFjdHVyZSBhbmdsZSIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iV19GcmFjdHVyZUhlaWdodCIgICAgIEFsaWFzPSLoo4LnvJ3pq5jluqYiICAgICBVbml0PSJtIiAgICBEZWZhdWx0PSIxMCIgICBNYXg9IjEwMDAwIiBNaW49IjFlLTA1IiBEaWdpdD0iNiIgRGVzYz0iZnJhY3R1cmUgaGVpZ2h0IiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJXX0ZyYWN0dXJlTWlkUG9pbnRIZWlnaHQiIEFsaWFzPSLoo4LnvJ3kuK3ngrnpq5jluqYiIFVuaXQ9Im0iIERlZmF1bHQ9IjUiIE1heD0iMTAwMDAiIE1pbj0iMCIgRGlnaXQ9IjYiIERlc2M9ImZyYWN0dXJlIG1pZHBvaW50IGhlaWdodCIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iV19GcmFjdHVyZVdpZHRoIiAgICAgIEFsaWFzPSLoo4LnvJ3lrr3luqYiICAgICBVbml0PSJtIiAgICBEZWZhdWx0PSIwLjAwMSIgTWF4PSIxMDAiICBNaW49IjFlLTA4IiBEaWdpdD0iOCIgRGVzYz0iZnJhY3R1cmUgd2lkdGgiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IldfRGZjIiAgICAgICAgICAgICAgICBBbGlhcz0i6KOC57yd5a+85rWB6IO95YqbIiBVbml0PSJtRC5tIiBEZWZhdWx0PSIxMDAwIiBNYXg9IjFlKzMwIiBNaW49IjAiICAgICBEaWdpdD0iNiIgRGVzYz0iZnJhY3R1cmUgY29uZHVjdGl2aXR5IiAvPg0KICA8L1BhcmFHcm91cD4NCg0KICA8UGFyYUdyb3VwIE5hbWU9IiIgQWxpYXM9IueLrOeri+ijgue8neWPguaVsCI+DQogICAgPFBhcmFJdGVtIE5hbWU9IkZfWDAiIEFsaWFzPSLotbfngrlYMCIgICBVbml0PSJtIiAgICBEZWZhdWx0PSIwIiBNYXg9IjEwMDAwIiBNaW49Ii0xMDAwMCIgRGlnaXQ9IjYiIERlc2M9ImZyYWN0dXJlIHN0YXJ0IFggY29vcmRpbmF0ZSIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iRl9ZMCIgQWxpYXM9Iui1t+eCuVkwIiAgIFVuaXQ9Im0iICAgIERlZmF1bHQ9IjAiIE1heD0iMTAwMDAiIE1pbj0iLTEwMDAwIiBEaWdpdD0iNiIgRGVzYz0iZnJhY3R1cmUgc3RhcnQgWSBjb29yZGluYXRlIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJGX1gxIiBBbGlhcz0i57uI54K5WDEiICAgVW5pdD0ibSIgICAgRGVmYXVsdD0iMCIgTWF4PSIxMDAwMCIgTWluPSItMTAwMDAiIERpZ2l0PSI2IiBEZXNjPSJmcmFjdHVyZSBlbmQgWCBjb29yZGluYXRlIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJGX1kxIiBBbGlhcz0i57uI54K5WTEiICAgVW5pdD0ibSIgICAgRGVmYXVsdD0iMCIgTWF4PSIxMDAwMCIgTWluPSItMTAwMDAiIERpZ2l0PSI2IiBEZXNjPSJmcmFjdHVyZSBlbmQgWSBjb29yZGluYXRlIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJGX0ZDIiBBbGlhcz0i5a+85rWB6IO95YqbIiBVbml0PSJtRC5tIiBEZWZhdWx0PSIxIiBNYXg9IjFlKzMwIiBNaW49IjAiICAgICAgRGlnaXQ9IjYiIERlc2M9ImZyYWN0dXJlIGNvbmR1Y3Rpdml0eSIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iRl9EVyIgQWxpYXM9Iuijgue8neWuveW6puWPguaVsCIgVW5pdD0iIiBEZWZhdWx0PSIxIiBNYXg9IjFlKzMwIiBNaW49IjAiIERpZ2l0PSI2IiBEZXNjPSJmcmFjdHVyZSB3aWR0aCBwYXJhbWV0ZXIiIC8+DQogIDwvUGFyYUdyb3VwPg0KDQogIDxQYXJhR3JvdXAgTmFtZT0iIiBBbGlhcz0i5pat5bGC5Y+C5pWwIj4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iRlRfWDAiIEFsaWFzPSLotbfngrlYMCIgVW5pdD0ibSIgRGVmYXVsdD0iMCIgTWF4PSIxMDAwMCIgTWluPSItMTAwMDAiIERpZ2l0PSI2IiBEZXNjPSJmYXVsdCBzdGFydCBYIGNvb3JkaW5hdGUiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IkZUX1kwIiBBbGlhcz0i6LW354K5WTAiIFVuaXQ9Im0iIERlZmF1bHQ9IjAiIE1heD0iMTAwMDAiIE1pbj0iLTEwMDAwIiBEaWdpdD0iNiIgRGVzYz0iZmF1bHQgc3RhcnQgWSBjb29yZGluYXRlIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJGVF9YMSIgQWxpYXM9Iue7iOeCuVgxIiBVbml0PSJtIiBEZWZhdWx0PSIwIiBNYXg9IjEwMDAwIiBNaW49Ii0xMDAwMCIgRGlnaXQ9IjYiIERlc2M9ImZhdWx0IGVuZCBYIGNvb3JkaW5hdGUiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IkZUX1kxIiBBbGlhcz0i57uI54K5WTEiIFVuaXQ9Im0iIERlZmF1bHQ9IjAiIE1heD0iMTAwMDAiIE1pbj0iLTEwMDAwIiBEaWdpdD0iNiIgRGVzYz0iZmF1bHQgZW5kIFkgY29vcmRpbmF0ZSIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iRlRfTGVha2FnZSIgQWxpYXM9IuazhOa8j+ezu+aVsCIgVW5pdD0iIiBEZWZhdWx0PSIxIiBNYXg9IjFlKzMwIiBNaW49IjAiIERpZ2l0PSI2IiBEZXNjPSJmYXVsdCBsZWFrYWdlIGNvZWZmaWNpZW50IiAvPg0KICA8L1BhcmFHcm91cD4NCg0KICA8UGFyYUdyb3VwIE5hbWU9IiIgQWxpYXM9IuefqeW9oui+ueeVjOWPguaVsCI+DQogICAgPFBhcmFJdGVtIE5hbWU9IkJSX1hNaW4iIEFsaWFzPSLlt6bovrnnlYxYIiBVbml0PSJtIiBEZWZhdWx0PSIwIiBNYXg9IjEwMDAwIiBNaW49Ii0xMDAwMCIgRGlnaXQ9IjYiIERlc2M9InJlY3RhbmdsZSBib3VuZGFyeSBtaW5pbXVtIFgiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IkJSX1lNaW4iIEFsaWFzPSLkuIvovrnnlYxZIiBVbml0PSJtIiBEZWZhdWx0PSIwIiBNYXg9IjEwMDAwIiBNaW49Ii0xMDAwMCIgRGlnaXQ9IjYiIERlc2M9InJlY3RhbmdsZSBib3VuZGFyeSBtaW5pbXVtIFkiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IkJSX1hNYXgiIEFsaWFzPSLlj7PovrnnlYxYIiBVbml0PSJtIiBEZWZhdWx0PSIwIiBNYXg9IjEwMDAwIiBNaW49Ii0xMDAwMCIgRGlnaXQ9IjYiIERlc2M9InJlY3RhbmdsZSBib3VuZGFyeSBtYXhpbXVtIFgiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IkJSX1lNYXgiIEFsaWFzPSLkuIrovrnnlYxZIiBVbml0PSJtIiBEZWZhdWx0PSIwIiBNYXg9IjEwMDAwIiBNaW49Ii0xMDAwMCIgRGlnaXQ9IjYiIERlc2M9InJlY3RhbmdsZSBib3VuZGFyeSBtYXhpbXVtIFkiIC8+DQogIDwvUGFyYUdyb3VwPg0KDQogIDxQYXJhR3JvdXAgTmFtZT0iIiBBbGlhcz0i5ZyG5b2i6L6555WM5Y+C5pWwIj4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iQkNfQ2VudGVyWCIgQWxpYXM9IuWchuW/g1giIFVuaXQ9Im0iIERlZmF1bHQ9IjAiIE1heD0iMTAwMDAiIE1pbj0iLTEwMDAwIiBEaWdpdD0iNiIgRGVzYz0iY2lyY2xlIGJvdW5kYXJ5IGNlbnRlciBYIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJCQ19DZW50ZXJZIiBBbGlhcz0i5ZyG5b+DWSIgVW5pdD0ibSIgRGVmYXVsdD0iMCIgTWF4PSIxMDAwMCIgTWluPSItMTAwMDAiIERpZ2l0PSI2IiBEZXNjPSJjaXJjbGUgYm91bmRhcnkgY2VudGVyIFkiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IkJDX1JhZGl1cyIgIEFsaWFzPSLljYrlvoQiICBVbml0PSJtIiBEZWZhdWx0PSIxIiBNYXg9IjEwMDAwIiBNaW49IjFlLTA1IiAgRGlnaXQ9IjYiIERlc2M9ImNpcmNsZSBib3VuZGFyeSByYWRpdXMiIC8+DQogIDwvUGFyYUdyb3VwPg0KDQogIDxQYXJhR3JvdXAgTmFtZT0iIiBBbGlhcz0i5aSa6L655b2i6L6555WM54K55Y+C5pWwIj4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iQlBfWCIgQWxpYXM9IljlnZDmoIciIFVuaXQ9Im0iIERlZmF1bHQ9IjAiIE1heD0iMTAwMDAiIE1pbj0iLTEwMDAwIiBEaWdpdD0iNiIgRGVzYz0icG9seWdvbiBib3VuZGFyeSB2ZXJ0ZXggWCIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iQlBfWSIgQWxpYXM9IlnlnZDmoIciIFVuaXQ9Im0iIERlZmF1bHQ9IjAiIE1heD0iMTAwMDAiIE1pbj0iLTEwMDAwIiBEaWdpdD0iNiIgRGVzYz0icG9seWdvbiBib3VuZGFyeSB2ZXJ0ZXggWSIgLz4NCiAgPC9QYXJhR3JvdXA+DQoNCiAgPFBhcmFHcm91cCBOYW1lPSIiIEFsaWFzPSLljLrln5/lj4LmlbAiPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJSX0xlYWthZ2UiIEFsaWFzPSLms4TpnLLns7vmlbAiIFVuaXQ9IiIgRGVmYXVsdD0iMSIgTWF4PSIxZSszMCIgTWluPSIwIiBEaWdpdD0iNiIgRGVzYz0icmVnaW9uIGxlYWthZ2UgY29lZmZpY2llbnQiIC8+DQogIDwvUGFyYUdyb3VwPg0KDQogIDxQYXJhR3JvdXAgTmFtZT0iIiBBbGlhcz0i5qCH6K6w5Yy65Z+f5Y+C5pWwIj4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iUk1fQ29tVyIgICAgICAgQWxpYXM9IuWCqOiDveavlCIgVW5pdD0iIiBEZWZhdWx0PSIxIiBNYXg9IjEiICAgIE1pbj0iMCIgICAgIERpZ2l0PSI2IiBEZXNjPSJzdG9yYWdlIHJhdGlvIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJSTV9Db21LciIgICAgICBBbGlhcz0i5rWB5bqm5q+UIiBVbml0PSIiIERlZmF1bHQ9IjEiIE1heD0iMTAwMCIgTWluPSIwLjAwMSIgRGlnaXQ9IjYiIERlc2M9Im1vYmlsaXR5IHJhdGlvIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJSTV9OZXRUb0dyb3NzIiBBbGlhcz0i5YeA5q+b5q+UIiBVbml0PSIiIERlZmF1bHQ9IjEiIE1heD0iMSIgICAgTWluPSIwIiAgICAgRGlnaXQ9IjYiIERlc2M9Im5ldC10by1ncm9zcyIgLz4NCiAgPC9QYXJhR3JvdXA+DQoNCiAgPCEtLSDnu5PmnpzpnaLmnb/lj4LmlbDlj6rnlLEgcmVidWlsZFJlc3VsdFBhcmFzKCkg6YCJ5oup77yM5LiN5Lya5Ye6546w5Zyo5bem5L6n6Z2i5p2/5Lit44CCIC0tPg0KICA8UGFyYUdyb3VwIE5hbWU9IiIgQWxpYXM9Iue7k+aenOWPguaVsCI+DQogICAgPFBhcmFJdGVtIE5hbWU9IlJlc3VsdF9XX1J3IiAgIEFsaWFzPSLkupXlvoQiICAgICAgICAgVW5pdD0ibSIgICAgICBEZWZhdWx0PSIwLjEiICAgIE1heD0iMTAiICAgIE1pbj0iMC4wMDEiICBEaWdpdD0iNiIgIERlc2M9InJlc3VsdCB3ZWxsYm9yZSByYWRpdXMiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IlJlc3VsdF9XX0RmYyIgIEFsaWFzPSLoo4LnvJ3lr7zmtYHog73lipsiIFVuaXQ9Im1ELm0iICAgRGVmYXVsdD0iMTAwMCIgICBNYXg9IjFlKzMwIiBNaW49IjAiICAgICAgRGlnaXQ9IjYiICBEZXNjPSJyZXN1bHQgZnJhY3R1cmUgY29uZHVjdGl2aXR5IiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJSZXN1bHRfV19Ta2luIiBBbGlhcz0i6KGo55qu57O75pWwIiAgICAgVW5pdD0iIiAgICAgICBEZWZhdWx0PSIwIiAgICAgIE1heD0iMTAwMCIgIE1pbj0iLTEwMCIgICBEaWdpdD0iNiIgIERlc2M9InJlc3VsdCBza2luIGZhY3RvciIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iUmVzdWx0X1dfQyIgICAgQWxpYXM9IuS6leetkuWCqOmbhuezu+aVsCIgVW5pdD0ibV4zL01QYSIgRGVmYXVsdD0iMCIgICAgICBNYXg9IjEwMDAiICBNaW49IjAiICAgICAgRGlnaXQ9IjYiICBEZXNjPSJyZXN1bHQgd2VsbGJvcmUgc3RvcmFnZSBjb2VmZmljaWVudCIgLz4NCg0KICAgIDxQYXJhSXRlbSBOYW1lPSJSZXN1bHRfUGkiICBBbGlhcz0i5Yid5aeL5Zyw5bGC5Y6L5YqbIiAgIFVuaXQ9Ik1QYSIgICBEZWZhdWx0PSI0MCIgICAgIE1heD0iNTAwIiAgIE1pbj0iMC4xIiAgIERpZ2l0PSI2IiAgRGVzYz0icmVzdWx0IGluaXRpYWwgZm9ybWF0aW9uIHByZXNzdXJlIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJSZXN1bHRfSyIgICBBbGlhcz0i5riX6YCP546HIiAgICAgICAgIFVuaXQ9Im1EIiAgICBEZWZhdWx0PSIyNSIgICAgIE1heD0iMTAwMDAiIE1pbj0iMCIgICAgIERpZ2l0PSI2IiAgRGVzYz0icmVzdWx0IHBlcm1lYWJpbGl0eSIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iUmVzdWx0X2giICAgQWxpYXM9IuWCqOWxguWOmuW6piIgICAgICAgVW5pdD0ibSIgICAgIERlZmF1bHQ9IjEwIiAgICAgTWF4PSIxMDAwMCIgTWluPSIxZS0wNSIgRGlnaXQ9IjYiICBEZXNjPSJyZXN1bHQgcmVzZXJ2b2lyIHRoaWNrbmVzcyIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iUmVzdWx0X3BoaSIgQWxpYXM9IuWtlOmameW6piIgICAgICAgICBVbml0PSIiICAgICAgRGVmYXVsdD0iMC4xIiAgICBNYXg9IjEiICAgICBNaW49IjFlLTA1IiBEaWdpdD0iNiIgIERlc2M9InJlc3VsdCBwb3Jvc2l0eSIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iUmVzdWx0X0N0aSIgQWxpYXM9Iue7vOWQiOWOi+e8qeezu+aVsCIgICBVbml0PSIxL01QYSIgRGVmYXVsdD0iMC4wMDEiICBNYXg9IjEwIiAgICBNaW49IjFlLTMwIiBEaWdpdD0iMTAiIFNjaWVudGlmaWM9IjEiIERlc2M9InJlc3VsdCB0b3RhbCBjb21wcmVzc2liaWxpdHkiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IlJlc3VsdF9DZiIgIEFsaWFzPSLlsqnnn7PljovnvKnns7vmlbAiICAgVW5pdD0iMS9NUGEiIERlZmF1bHQ9IjAuMDAwMSIgTWF4PSIxMCIgICAgTWluPSIxZS0zMCIgRGlnaXQ9IjEwIiBTY2llbnRpZmljPSIxIiBEZXNjPSJyZXN1bHQgcm9jayBjb21wcmVzc2liaWxpdHkiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IlJlc3VsdF9Tb2kiIEFsaWFzPSLliJ3lp4vlkKvmsrnppbHlkozluqYiIFVuaXQ9IiIgICAgICBEZWZhdWx0PSIwLjgiICAgIE1heD0iMSIgICAgIE1pbj0iMCIgICAgIERpZ2l0PSI2IiAgRGVzYz0icmVzdWx0IGluaXRpYWwgb2lsIHNhdHVyYXRpb24iIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IlJlc3VsdF9TZ2kiIEFsaWFzPSLliJ3lp4vlkKvmsJTppbHlkozluqYiIFVuaXQ9IiIgICAgICBEZWZhdWx0PSIwIiAgICAgIE1heD0iMSIgICAgIE1pbj0iMCIgICAgIERpZ2l0PSI2IiAgRGVzYz0icmVzdWx0IGluaXRpYWwgZ2FzIHNhdHVyYXRpb24iIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IlJlc3VsdF9Td2kiIEFsaWFzPSLliJ3lp4vlkKvmsLTppbHlkozluqYiIFVuaXQ9IiIgICAgICBEZWZhdWx0PSIwLjIiICAgIE1heD0iMSIgICAgIE1pbj0iMCIgICAgIERpZ2l0PSI2IiAgRGVzYz0icmVzdWx0IGluaXRpYWwgd2F0ZXIgc2F0dXJhdGlvbiIgLz4NCg0KICAgIDxQYXJhSXRlbSBOYW1lPSJSZXN1bHRfQm8iICAgQWxpYXM9IuayueS9k+enr+ezu+aVsCIgVW5pdD0iIiAgICAgIERlZmF1bHQ9IjEiIE1heD0iMWUrMzAiIE1pbj0iMCIgICAgIERpZ2l0PSI2IiAgRGVzYz0icmVzdWx0IG9pbCBmb3JtYXRpb24gdm9sdW1lIGZhY3RvciIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iUmVzdWx0X01pdW8iIEFsaWFzPSLmsrnnm7jpu4/luqYiICAgVW5pdD0ibVBhLnMiIERlZmF1bHQ9IjEiIE1heD0iMWUrMzAiIE1pbj0iMWUtMzAiIERpZ2l0PSI2IiAgRGVzYz0icmVzdWx0IG9pbCB2aXNjb3NpdHkiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IlJlc3VsdF9DbyIgICBBbGlhcz0i5rK55Y6L57yp57O75pWwIiBVbml0PSIxL01QYSIgRGVmYXVsdD0iMCIgTWF4PSIxZSszMCIgTWluPSIwIiAgICBEaWdpdD0iMTAiIFNjaWVudGlmaWM9IjEiIERlc2M9InJlc3VsdCBvaWwgY29tcHJlc3NpYmlsaXR5IiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJSZXN1bHRfQnciICAgQWxpYXM9IuawtOS9k+enr+ezu+aVsCIgVW5pdD0ibTMvbTMiIERlZmF1bHQ9IjEiIE1heD0iMWUrMzAiIE1pbj0iMCIgICAgIERpZ2l0PSI2IiAgRGVzYz0icmVzdWx0IHdhdGVyIGZvcm1hdGlvbiB2b2x1bWUgZmFjdG9yIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJSZXN1bHRfTWl1dyIgQWxpYXM9IuawtOebuOm7j+W6piIgICBVbml0PSJtUGEucyIgRGVmYXVsdD0iMSIgTWF4PSIxZSszMCIgTWluPSIxZS0zMCIgRGlnaXQ9IjYiICBEZXNjPSJyZXN1bHQgd2F0ZXIgdmlzY29zaXR5IiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJSZXN1bHRfQ3ciICAgQWxpYXM9IuawtOWOi+e8qeezu+aVsCIgVW5pdD0iMS9NUGEiIERlZmF1bHQ9IjAiIE1heD0iMWUrMzAiIE1pbj0iMCIgICAgRGlnaXQ9IjEwIiBTY2llbnRpZmljPSIxIiBEZXNjPSJyZXN1bHQgd2F0ZXIgY29tcHJlc3NpYmlsaXR5IiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJSZXN1bHRfQmciICAgQWxpYXM9IuawlOS9k+enr+ezu+aVsCIgVW5pdD0ibTMvbTMiIERlZmF1bHQ9IjEiIE1heD0iMWUrMzAiIE1pbj0iMCIgICAgIERpZ2l0PSI2IiAgRGVzYz0icmVzdWx0IGdhcyBmb3JtYXRpb24gdm9sdW1lIGZhY3RvciIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iUmVzdWx0X01pdWciIEFsaWFzPSLmsJTnm7jpu4/luqYiICAgVW5pdD0ibVBhLnMiIERlZmF1bHQ9IjEiIE1heD0iMWUrMzAiIE1pbj0iMWUtMzAiIERpZ2l0PSI2IiAgRGVzYz0icmVzdWx0IGdhcyB2aXNjb3NpdHkiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IlJlc3VsdF9DZyIgICBBbGlhcz0i5rCU5Y6L57yp57O75pWwIiBVbml0PSIxL01QYSIgRGVmYXVsdD0iMCIgTWF4PSIxZSszMCIgTWluPSIwIiAgICBEaWdpdD0iMTAiIFNjaWVudGlmaWM9IjEiIERlc2M9InJlc3VsdCBnYXMgY29tcHJlc3NpYmlsaXR5IiAvPg0KICA8L1BhcmFHcm91cD4NCg0KPC9Sb290Pg0K \ No newline at end of file +PD94bWwgdmVycup_mpac2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4NCg0KPCEtLSoqKioqKioqKioqKiwzyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiotLT4NCjwhLS0gICAg5pys5paH5qGj55qE55uu55qE5piv5bu656uLV1RBSeaVsOWAvOinoyhOTSnmqKHlnZfnmoTlj4LmlbDlrprkuYkgICAgICAgICAgICAgICAgLS0+DQo8IS0tICAgIOS7heWMheWQq1BFQknmsYLop6PlmajmiYDpnIDnmoTlgqjlsYLjgIHkupXlkozlh6DkvZXlr7nosaHlj4LmlbAgICAgICAgICAgICAgICAgICAtLT4NCjwhLS0gICAgRGF0ZTogMjAyNjA2MTUgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC0tPg0KPCEtLSoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiotLT4NCg0KPCEtLQ0KICAgIOWPguaVsOiMg+WbtO+8mlBFQknmsYLop6PlmajmiYDpnIDnmoTlgqjlsYLjgIHkupXlkozlh6DkvZXlr7nosaHlj4LmlbANCiAgICDlr7nlupQgSFhfTldUTV9NT0RFTF9JTlBVVCDnu5PmnoTkvZPlrZfmrrUNCiAgICDpgJrov4cgX3BhcmFIZWxwZXItPmxvYWRQYXJhRGVmaW5lcygpIOWKoOi9ve+8jHNLZXkg5qCH6K+G5Li6IHNfTm1fU2VyaWUNCi0tPg0KDQo8Um9vdD4NCg0KICA8UGFyYUdyb3VwIE5hbWU9IiIgQWxpYXM9IuaXtumXtOatpeiuvue9riI+DQogICAgPFBhcmFJdGVtIE5hbWU9Ik5NX1RpbWVHcm93dGhFeHBvbmVudCIgQWxpYXM9IuaXtumXtOWinumVv+aMh+aVsCIgVW5pdD0iIiAgRGVmYXVsdD0iMS4wNSIgICBNYXg9IjEwIiAgICBNaW49IjEiICAgICBEaWdpdD0iNiIgRGVzYz0idGltZSBncm93dGggZXhwb25lbnQiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9Ik5NX0R0TWluIiAgICAgICAgICAgICAgQWxpYXM9IuacgOWwj+aXtumXtOatpSIgICBVbml0PSJoIiBEZWZhdWx0PSIwLjAwMjUiIE1heD0iMWUrMzAiIE1pbj0iMWUtMTIiIERpZ2l0PSI2IiBEZXNjPSJtaW5pbXVtIHRpbWUgc3RlcCIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iTk1fRHRNYXgiICAgICAgICAgICAgICBBbGlhcz0i5pyA5aSn5pe26Ze05q2lIiAgIFVuaXQ9ImgiIERlZmF1bHQ9IjEyLjUiICAgTWF4PSIxZSszMCIgTWluPSIxZS0xMiIgRGlnaXQ9IjYiIERlc2M9Im1heGltdW0gdGltZSBzdGVwIiAvPg0KICA8L1BhcmFHcm91cD4NCg0KICA8UGFyYUdyb3VwIE5hbWU9IiIgQWxpYXM9IuWCqOWxguWPguaVsCI+DQogICAgPFBhcmFJdGVtIE5hbWU9ImgiICAgQWxpYXM9IuWCqOWxguWOmuW6piIgICAgICAgVW5pdD0ibSIgICAgIERlZmF1bHQ9IjEwIiAgICBNYXg9IjEwMDAwIiAgTWluPSIxZS0wNSIgIERpZ2l0PSI2IiAgRGVzYz0icmVzZXJ2b2lyIHRoaWNrbmVzcyIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iUGkiICBBbGlhcz0i5Yid5aeL5Y6L5YqbIiAgICAgICBVbml0PSJNUGEiICAgRGVmYXVsdD0iNDAiICAgIE1heD0iNTAwIiAgICBNaW49IjAuMSIgICAgRGlnaXQ9IjYiICBEZXNjPSJpbml0aWFsIGZvcm1hdGlvbiBwcmVzc3VyZSIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iSyIgICBBbGlhcz0i5riX6YCP546HIiAgICAgICAgIFVuaXQ9Im1EIiAgICBEZWZhdWx0PSIyNSIgICAgTWF4PSIxMDAwMCIgIE1pbj0iMCIgICAgICBEaWdpdD0iNiIgIERlc2M9InBlcm1lYWJpbGl0eSIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0icGhpIiBBbGlhcz0i5a2U6ZqZ5bqmIiAgICAgICAgIFVuaXQ9IiIgICAgICBEZWZhdWx0PSIwLjEiICAgTWF4PSIxIiAgICAgIE1pbj0iMWUtMDUiICBEaWdpdD0iNiIgIERlc2M9InBvcm9zaXR5IiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJCbyIgIEFsaWFzPSLmsrnkvZPnp6/ns7vmlbAiICAgICBVbml0PSIiICAgICAgRGVmYXVsdD0iMS4yIiAgIE1heD0iMTAiICAgICBNaW49IjFlLTA2IiAgRGlnaXQ9IjYiICBEZXNjPSJvaWwgZm9ybWF0aW9uIHZvbHVtZSBmYWN0b3IiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9Ik1pdW8iIEFsaWFzPSLmsrnnm7jpu4/luqYiICAgICAgVW5pdD0ibVBhLnMiIERlZmF1bHQ9IjAuNSIgICBNYXg9IjEwMDAwIiAgTWluPSIxZS0wNiIgIERpZ2l0PSI2IiAgRGVzYz0ib2lsIHZpc2Nvc2l0eSIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iQnciICBBbGlhcz0i5rC05L2T56ev57O75pWwIiAgICAgVW5pdD0iIiAgICAgIERlZmF1bHQ9IjEiICAgICBNYXg9IjEwIiAgICAgTWluPSIxZS0wNiIgIERpZ2l0PSI2IiAgRGVzYz0id2F0ZXIgZm9ybWF0aW9uIHZvbHVtZSBmYWN0b3IiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9Ik1pdXciIEFsaWFzPSLmsLTnm7jpu4/luqYiICAgICAgVW5pdD0ibVBhLnMiIERlZmF1bHQ9IjEiICAgICBNYXg9IjEwMDAwIiAgTWluPSIxZS0wNiIgIERpZ2l0PSI2IiAgRGVzYz0id2F0ZXIgdmlzY29zaXR5IiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJDdGkiIEFsaWFzPSLnu7zlkIjljovnvKnns7vmlbAiICAgVW5pdD0iMS9NUGEiIERlZmF1bHQ9IjAuMDAxIiBNYXg9IjEwIiAgICAgTWluPSIxZS0zMCIgIERpZ2l0PSIxMCIgU2NpZW50aWZpYz0iMSIgRGVzYz0idG90YWwgY29tcHJlc3NpYmlsaXR5IiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJDZiIgIEFsaWFzPSLlsqnnn7PljovnvKnns7vmlbAiICAgVW5pdD0iMS9NUGEiIERlZmF1bHQ9IjAuMDAwMSIgTWF4PSIxMCIgICAgTWluPSIxZS0zMCIgIERpZ2l0PSIxMCIgU2NpZW50aWZpYz0iMSIgRGVzYz0icm9jayBjb21wcmVzc2liaWxpdHkiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IlNvaSIgQWxpYXM9IuWIneWni+WQq+ayuemlseWSjOW6piIgVW5pdD0iIiAgICAgIERlZmF1bHQ9IjAuOCIgICBNYXg9IjEiICAgICAgTWluPSIwIiAgICAgIERpZ2l0PSI2IiAgRGVzYz0iaW5pdGlhbCBvaWwgc2F0dXJhdGlvbiIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iU2dpIiBBbGlhcz0i5Yid5aeL5ZCr5rCU6aWx5ZKM5bqmIiBVbml0PSIiICAgICAgRGVmYXVsdD0iMCIgICAgIE1heD0iMSIgICAgICBNaW49IjAiICAgICAgRGlnaXQ9IjYiICBEZXNjPSJpbml0aWFsIGdhcyBzYXR1cmF0aW9uIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJTd2kiIEFsaWFzPSLliJ3lp4vlkKvmsLTppbHlkozluqYiIFVuaXQ9IiIgICAgICBEZWZhdWx0PSIwLjIiICAgTWF4PSIxIiAgICAgIE1pbj0iMCIgICAgICBEaWdpdD0iNiIgIERlc2M9ImluaXRpYWwgd2F0ZXIgc2F0dXJhdGlvbiIgLz4NCiAgPC9QYXJhR3JvdXA+DQoNCiAgPFBhcmFHcm91cCBOYW1lPSIiIEFsaWFzPSLkupXlj4LmlbAiPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJXX1giICAgIEFsaWFzPSJY5Z2Q5qCHIiAgICAgICBVbml0PSJtIiAgICBEZWZhdWx0PSIwIiAgICAgTWF4PSIxMDAwMCIgIE1pbj0iLTEwMDAwIiBEaWdpdD0iNiIgIERlc2M9IndlbGwgWCBjb29yZGluYXRlIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJXX1kiICAgIEFsaWFzPSJZ5Z2Q5qCHIiAgICAgICBVbml0PSJtIiAgICBEZWZhdWx0PSIwIiAgICAgTWF4PSIxMDAwMCIgIE1pbj0iLTEwMDAwIiBEaWdpdD0iNiIgIERlc2M9IndlbGwgWSBjb29yZGluYXRlIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJXX1J3IiAgIEFsaWFzPSLkupXnrZLljYrlvoQiICAgIFVuaXQ9Im0iICAgIERlZmF1bHQ9IjAuMSIgICBNYXg9IjEwIiAgICAgTWluPSIwLjAwMSIgIERpZ2l0PSI2IiAgRGVzYz0id2VsbGJvcmUgcmFkaXVzIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJXX1NraW4iIEFsaWFzPSLooajnmq7ns7vmlbAiICAgIFVuaXQ9IiIgICAgIERlZmF1bHQ9IjAiICAgICBNYXg9IjEwMDAiICAgTWluPSItMTAwIiAgIERpZ2l0PSI2IiAgRGVzYz0ic2tpbiBmYWN0b3IiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IldfQyIgICAgQWxpYXM9IuS6leetkuWCqOmbhuezu+aVsCIgVW5pdD0ibV4zL01QYSIgRGVmYXVsdD0iMCIgTWF4PSIxMDAwIiAgIE1pbj0iMCIgICAgICBEaWdpdD0iNiIgIERlc2M9IndlbGxib3JlIHN0b3JhZ2UgY29lZmZpY2llbnQiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IldfQm90dG9taG9sZU1EIiAgICAgICBBbGlhcz0i5LqV5bqVTUQiICAgICAgIFVuaXQ9Im0iICAgIERlZmF1bHQ9IjYwMDAiIE1heD0iMTAwMDAwIiBNaW49IjAiICAgICBEaWdpdD0iNiIgRGVzYz0iYm90dG9taG9sZSBtZWFzdXJlZCBkZXB0aCIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iV19XZWxsTGVuZ3RoIiAgICAgICAgIEFsaWFzPSLkupXouqvplb/luqYiICAgICBVbml0PSJtIiAgICBEZWZhdWx0PSIyMDAiICBNYXg9IjEwMDAwIiAgTWluPSIxZS0wNSIgRGlnaXQ9IjYiIERlc2M9IndlbGxib3JlIGxlbmd0aCIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iV19QZXJmb3JhdGlvbk1kU3RhcnQiIEFsaWFzPSLlsITlrZTotbflp4tNRCIgICBVbml0PSJtIiAgICBEZWZhdWx0PSI2MDAwIiBNYXg9IjEwMDAwMCIgTWluPSIwIiAgICAgRGlnaXQ9IjYiIERlc2M9InBlcmZvcmF0aW9uIHN0YXJ0IG1lYXN1cmVkIGRlcHRoIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJXX1BlcmZvcmF0aW9uTWRFbmQiICAgQWxpYXM9IuWwhOWtlOe7k+adn01EIiAgIFVuaXQ9Im0iICAgIERlZmF1bHQ9IjYwMzAiIE1heD0iMTAwMDAwIiBNaW49IjAiICAgICBEaWdpdD0iNiIgRGVzYz0icGVyZm9yYXRpb24gZW5kIG1lYXN1cmVkIGRlcHRoIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJXX0RyYWluQW5nbGUiICAgICAgICAgQWxpYXM9IuaOkuawtOinkuW6piIgICAgIFVuaXQ9ImRlZyIgIERlZmF1bHQ9IjAiICAgIE1heD0iMzYwIiAgIE1pbj0iLTM2MCIgIERpZ2l0PSI2IiBEZXNjPSJob3Jpem9udGFsIHdlbGwgZHJhaW4gYW5nbGUiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IldfTnVtYmVyT2ZGcmFjdHVyZXMiICBBbGlhcz0i6KOC57yd5pWw6YePIiAgICAgVW5pdD0iIiAgICAgRGVmYXVsdD0iMTUiICAgTWF4PSIxMDAwIiAgTWluPSIyIiAgICAgRGlnaXQ9IjAiIERlc2M9Im51bWJlciBvZiBmcmFjdHVyZXMiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IldfRnJhY3R1cmVIYWxmTGVuZ3RoIiBBbGlhcz0i6KOC57yd5Y2K6ZW/IiAgICAgVW5pdD0ibSIgICAgRGVmYXVsdD0iNTAiICAgTWF4PSIxMDAwMCIgTWluPSIxZS0wNSIgRGlnaXQ9IjYiIERlc2M9ImZyYWN0dXJlIGhhbGYtbGVuZ3RoIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJXX0ZyYWN0dXJlQW5nbGUiICAgICAgQWxpYXM9Iuijgue8neinkuW6piIgICAgIFVuaXQ9ImRlZyIgIERlZmF1bHQ9IjkwIiAgIE1heD0iMzYwIiAgIE1pbj0iLTM2MCIgIERpZ2l0PSI2IiBEZXNjPSJmcmFjdHVyZSBhbmdsZSIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iV19GcmFjdHVyZUhlaWdodCIgICAgIEFsaWFzPSLoo4LnvJ3pq5jluqYiICAgICBVbml0PSJtIiAgICBEZWZhdWx0PSIxMCIgICBNYXg9IjEwMDAwIiBNaW49IjFlLTA1IiBEaWdpdD0iNiIgRGVzYz0iZnJhY3R1cmUgaGVpZ2h0IiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJXX0ZyYWN0dXJlTWlkUG9pbnRIZWlnaHQiIEFsaWFzPSLoo4LnvJ3kuK3ngrnpq5jluqYiIFVuaXQ9Im0iIERlZmF1bHQ9IjUiIE1heD0iMTAwMDAiIE1pbj0iMCIgRGlnaXQ9IjYiIERlc2M9ImZyYWN0dXJlIG1pZHBvaW50IGhlaWdodCIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iV19GcmFjdHVyZVdpZHRoIiAgICAgIEFsaWFzPSLoo4LnvJ3lrr3luqYiICAgICBVbml0PSJtIiAgICBEZWZhdWx0PSIwLjAwMSIgTWF4PSIxMDAiICBNaW49IjFlLTA4IiBEaWdpdD0iOCIgRGVzYz0iZnJhY3R1cmUgd2lkdGgiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IldfRGZjIiAgICAgICAgICAgICAgICBBbGlhcz0i6KOC57yd5a+85rWB6IO95YqbIiBVbml0PSJtRC5tIiBEZWZhdWx0PSIxMDAwIiBNYXg9IjFlKzMwIiBNaW49IjAiICAgICBEaWdpdD0iNiIgRGVzYz0iZnJhY3R1cmUgY29uZHVjdGl2aXR5IiAvPg0KICA8L1BhcmFHcm91cD4NCg0KICA8UGFyYUdyb3VwIE5hbWU9IiIgQWxpYXM9IueLrOeri+ijgue8neWPguaVsCI+DQogICAgPFBhcmFJdGVtIE5hbWU9IkZfWDAiIEFsaWFzPSLotbfngrlYMCIgICBVbml0PSJtIiAgICBEZWZhdWx0PSIwIiBNYXg9IjEwMDAwIiBNaW49Ii0xMDAwMCIgRGlnaXQ9IjYiIERlc2M9ImZyYWN0dXJlIHN0YXJ0IFggY29vcmRpbmF0ZSIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iRl9ZMCIgQWxpYXM9Iui1t+eCuVkwIiAgIFVuaXQ9Im0iICAgIERlZmF1bHQ9IjAiIE1heD0iMTAwMDAiIE1pbj0iLTEwMDAwIiBEaWdpdD0iNiIgRGVzYz0iZnJhY3R1cmUgc3RhcnQgWSBjb29yZGluYXRlIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJGX1gxIiBBbGlhcz0i57uI54K5WDEiICAgVW5pdD0ibSIgICAgRGVmYXVsdD0iMCIgTWF4PSIxMDAwMCIgTWluPSItMTAwMDAiIERpZ2l0PSI2IiBEZXNjPSJmcmFjdHVyZSBlbmQgWCBjb29yZGluYXRlIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJGX1kxIiBBbGlhcz0i57uI54K5WTEiICAgVW5pdD0ibSIgICAgRGVmYXVsdD0iMCIgTWF4PSIxMDAwMCIgTWluPSItMTAwMDAiIERpZ2l0PSI2IiBEZXNjPSJmcmFjdHVyZSBlbmQgWSBjb29yZGluYXRlIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJGX0ZDIiBBbGlhcz0i5a+85rWB6IO95YqbIiBVbml0PSJtRC5tIiBEZWZhdWx0PSIxIiBNYXg9IjFlKzMwIiBNaW49IjAiICAgICAgRGlnaXQ9IjYiIERlc2M9ImZyYWN0dXJlIGNvbmR1Y3Rpdml0eSIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iRl9EVyIgQWxpYXM9Iuijgue8neWuveW6puWPguaVsCIgVW5pdD0iIiBEZWZhdWx0PSIxIiBNYXg9IjFlKzMwIiBNaW49IjAiIERpZ2l0PSI2IiBEZXNjPSJmcmFjdHVyZSB3aWR0aCBwYXJhbWV0ZXIiIC8+DQogIDwvUGFyYUdyb3VwPg0KDQogIDxQYXJhR3JvdXAgTmFtZT0iIiBBbGlhcz0i5pat5bGC5Y+C5pWwIj4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iRlRfWDAiIEFsaWFzPSLotbfngrlYMCIgVW5pdD0ibSIgRGVmYXVsdD0iMCIgTWF4PSIxMDAwMCIgTWluPSItMTAwMDAiIERpZ2l0PSI2IiBEZXNjPSJmYXVsdCBzdGFydCBYIGNvb3JkaW5hdGUiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IkZUX1kwIiBBbGlhcz0i6LW354K5WTAiIFVuaXQ9Im0iIERlZmF1bHQ9IjAiIE1heD0iMTAwMDAiIE1pbj0iLTEwMDAwIiBEaWdpdD0iNiIgRGVzYz0iZmF1bHQgc3RhcnQgWSBjb29yZGluYXRlIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJGVF9YMSIgQWxpYXM9Iue7iOeCuVgxIiBVbml0PSJtIiBEZWZhdWx0PSIwIiBNYXg9IjEwMDAwIiBNaW49Ii0xMDAwMCIgRGlnaXQ9IjYiIERlc2M9ImZhdWx0IGVuZCBYIGNvb3JkaW5hdGUiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IkZUX1kxIiBBbGlhcz0i57uI54K5WTEiIFVuaXQ9Im0iIERlZmF1bHQ9IjAiIE1heD0iMTAwMDAiIE1pbj0iLTEwMDAwIiBEaWdpdD0iNiIgRGVzYz0iZmF1bHQgZW5kIFkgY29vcmRpbmF0ZSIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iRlRfTGVha2FnZSIgQWxpYXM9IuazhOa8j+ezu+aVsCIgVW5pdD0iIiBEZWZhdWx0PSIxIiBNYXg9IjFlKzMwIiBNaW49IjAiIERpZ2l0PSI2IiBEZXNjPSJmYXVsdCBsZWFrYWdlIGNvZWZmaWNpZW50IiAvPg0KICA8L1BhcmFHcm91cD4NCg0KICA8UGFyYUdyb3VwIE5hbWU9IiIgQWxpYXM9IuefqeW9oui+ueeVjOWPguaVsCI+DQogICAgPFBhcmFJdGVtIE5hbWU9IkJSX1hNaW4iIEFsaWFzPSLlt6bovrnnlYxYIiBVbml0PSJtIiBEZWZhdWx0PSIwIiBNYXg9IjEwMDAwIiBNaW49Ii0xMDAwMCIgRGlnaXQ9IjYiIERlc2M9InJlY3RhbmdsZSBib3VuZGFyeSBtaW5pbXVtIFgiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IkJSX1lNaW4iIEFsaWFzPSLkuIvovrnnlYxZIiBVbml0PSJtIiBEZWZhdWx0PSIwIiBNYXg9IjEwMDAwIiBNaW49Ii0xMDAwMCIgRGlnaXQ9IjYiIERlc2M9InJlY3RhbmdsZSBib3VuZGFyeSBtaW5pbXVtIFkiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IkJSX1hNYXgiIEFsaWFzPSLlj7PovrnnlYxYIiBVbml0PSJtIiBEZWZhdWx0PSIwIiBNYXg9IjEwMDAwIiBNaW49Ii0xMDAwMCIgRGlnaXQ9IjYiIERlc2M9InJlY3RhbmdsZSBib3VuZGFyeSBtYXhpbXVtIFgiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IkJSX1lNYXgiIEFsaWFzPSLkuIrovrnnlYxZIiBVbml0PSJtIiBEZWZhdWx0PSIwIiBNYXg9IjEwMDAwIiBNaW49Ii0xMDAwMCIgRGlnaXQ9IjYiIERlc2M9InJlY3RhbmdsZSBib3VuZGFyeSBtYXhpbXVtIFkiIC8+DQogIDwvUGFyYUdyb3VwPg0KDQogIDxQYXJhR3JvdXAgTmFtZT0iIiBBbGlhcz0i5ZyG5b2i6L6555WM5Y+C5pWwIj4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iQkNfQ2VudGVyWCIgQWxpYXM9IuWchuW/g1giIFVuaXQ9Im0iIERlZmF1bHQ9IjAiIE1heD0iMTAwMDAiIE1pbj0iLTEwMDAwIiBEaWdpdD0iNiIgRGVzYz0iY2lyY2xlIGJvdW5kYXJ5IGNlbnRlciBYIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJCQ19DZW50ZXJZIiBBbGlhcz0i5ZyG5b+DWSIgVW5pdD0ibSIgRGVmYXVsdD0iMCIgTWF4PSIxMDAwMCIgTWluPSItMTAwMDAiIERpZ2l0PSI2IiBEZXNjPSJjaXJjbGUgYm91bmRhcnkgY2VudGVyIFkiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IkJDX1JhZGl1cyIgIEFsaWFzPSLljYrlvoQiICBVbml0PSJtIiBEZWZhdWx0PSIxIiBNYXg9IjEwMDAwIiBNaW49IjFlLTA1IiAgRGlnaXQ9IjYiIERlc2M9ImNpcmNsZSBib3VuZGFyeSByYWRpdXMiIC8+DQogIDwvUGFyYUdyb3VwPg0KDQogIDxQYXJhR3JvdXAgTmFtZT0iIiBBbGlhcz0i5aSa6L655b2i6L6555WM54K55Y+C5pWwIj4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iQlBfWCIgQWxpYXM9IljlnZDmoIciIFVuaXQ9Im0iIERlZmF1bHQ9IjAiIE1heD0iMTAwMDAiIE1pbj0iLTEwMDAwIiBEaWdpdD0iNiIgRGVzYz0icG9seWdvbiBib3VuZGFyeSB2ZXJ0ZXggWCIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iQlBfWSIgQWxpYXM9IlnlnZDmoIciIFVuaXQ9Im0iIERlZmF1bHQ9IjAiIE1heD0iMTAwMDAiIE1pbj0iLTEwMDAwIiBEaWdpdD0iNiIgRGVzYz0icG9seWdvbiBib3VuZGFyeSB2ZXJ0ZXggWSIgLz4NCiAgPC9QYXJhR3JvdXA+DQoNCiAgPFBhcmFHcm91cCBOYW1lPSIiIEFsaWFzPSLljLrln5/lj4LmlbAiPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJSX0xlYWthZ2UiIEFsaWFzPSLms4TpnLLns7vmlbAiIFVuaXQ9IiIgRGVmYXVsdD0iMSIgTWF4PSIxZSszMCIgTWluPSIwIiBEaWdpdD0iNiIgRGVzYz0icmVnaW9uIGxlYWthZ2UgY29lZmZpY2llbnQiIC8+DQogIDwvUGFyYUdyb3VwPg0KDQogIDxQYXJhR3JvdXAgTmFtZT0iIiBBbGlhcz0i5qCH6K6w5Yy65Z+f5Y+C5pWwIj4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iUk1fQ29tVyIgICAgICAgQWxpYXM9IuWCqOiDveavlCIgVW5pdD0iIiBEZWZhdWx0PSIxIiBNYXg9IjEiICAgIE1pbj0iMCIgICAgIERpZ2l0PSI2IiBEZXNjPSJzdG9yYWdlIHJhdGlvIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJSTV9Db21LciIgICAgICBBbGlhcz0i5rWB5bqm5q+UIiBVbml0PSIiIERlZmF1bHQ9IjEiIE1heD0iMTAwMCIgTWluPSIwLjAwMSIgRGlnaXQ9IjYiIERlc2M9Im1vYmlsaXR5IHJhdGlvIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJSTV9OZXRUb0dyb3NzIiBBbGlhcz0i5YeA5q+b5q+UIiBVbml0PSIiIERlZmF1bHQ9IjEiIE1heD0iMSIgICAgTWluPSIwIiAgICAgRGlnaXQ9IjYiIERlc2M9Im5ldC10by1ncm9zcyIgLz4NCiAgPC9QYXJhR3JvdXA+DQoNCiAgPCEtLSDnu5PmnpzpnaLmnb/lj4LmlbDlj6rnlLEgcmVidWlsZFJlc3VsdFBhcmFzKCkg6YCJ5oup77yM5LiN5Lya5Ye6546w5Zyo5bem5L6n6Z2i5p2/5Lit44CCIC0tPg0KICA8UGFyYUdyb3VwIE5hbWU9IiIgQWxpYXM9Iue7k+aenOWPguaVsCI+DQogICAgPFBhcmFJdGVtIE5hbWU9IlJlc3VsdF9XX1J3IiAgIEFsaWFzPSLkupXlvoQiICAgICAgICAgVW5pdD0ibSIgICAgICBEZWZhdWx0PSIwLjEiICAgIE1heD0iMTAiICAgIE1pbj0iMC4wMDEiICBEaWdpdD0iNiIgIERlc2M9InJlc3VsdCB3ZWxsYm9yZSByYWRpdXMiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IlJlc3VsdF9XX0RmYyIgIEFsaWFzPSLoo4LnvJ3lr7zmtYHog73lipsiIFVuaXQ9Im1ELm0iICAgRGVmYXVsdD0iMTAwMCIgICBNYXg9IjFlKzMwIiBNaW49IjAiICAgICAgRGlnaXQ9IjYiICBEZXNjPSJyZXN1bHQgZnJhY3R1cmUgY29uZHVjdGl2aXR5IiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJSZXN1bHRfV19Ta2luIiBBbGlhcz0i6KGo55qu57O75pWwIiAgICAgVW5pdD0iIiAgICAgICBEZWZhdWx0PSIwIiAgICAgIE1heD0iMTAwMCIgIE1pbj0iLTEwMCIgICBEaWdpdD0iNiIgIERlc2M9InJlc3VsdCBza2luIGZhY3RvciIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iUmVzdWx0X1dfQyIgICAgQWxpYXM9IuS6leetkuWCqOmbhuezu+aVsCIgVW5pdD0ibV4zL01QYSIgRGVmYXVsdD0iMCIgICAgICBNYXg9IjEwMDAiICBNaW49IjAiICAgICAgRGlnaXQ9IjYiICBEZXNjPSJyZXN1bHQgd2VsbGJvcmUgc3RvcmFnZSBjb2VmZmljaWVudCIgLz4NCg0KICAgIDxQYXJhSXRlbSBOYW1lPSJSZXN1bHRfUGkiICBBbGlhcz0i5Yid5aeL5Zyw5bGC5Y6L5YqbIiAgIFVuaXQ9Ik1QYSIgICBEZWZhdWx0PSI0MCIgICAgIE1heD0iNTAwIiAgIE1pbj0iMC4xIiAgIERpZ2l0PSI2IiAgRGVzYz0icmVzdWx0IGluaXRpYWwgZm9ybWF0aW9uIHByZXNzdXJlIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJSZXN1bHRfSyIgICBBbGlhcz0i5riX6YCP546HIiAgICAgICAgIFVuaXQ9Im1EIiAgICBEZWZhdWx0PSIyNSIgICAgIE1heD0iMTAwMDAiIE1pbj0iMCIgICAgIERpZ2l0PSI2IiAgRGVzYz0icmVzdWx0IHBlcm1lYWJpbGl0eSIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iUmVzdWx0X2giICAgQWxpYXM9IuWCqOWxguWOmuW6piIgICAgICAgVW5pdD0ibSIgICAgIERlZmF1bHQ9IjEwIiAgICAgTWF4PSIxMDAwMCIgTWluPSIxZS0wNSIgRGlnaXQ9IjYiICBEZXNjPSJyZXN1bHQgcmVzZXJ2b2lyIHRoaWNrbmVzcyIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iUmVzdWx0X3BoaSIgQWxpYXM9IuWtlOmameW6piIgICAgICAgICBVbml0PSIiICAgICAgRGVmYXVsdD0iMC4xIiAgICBNYXg9IjEiICAgICBNaW49IjFlLTA1IiBEaWdpdD0iNiIgIERlc2M9InJlc3VsdCBwb3Jvc2l0eSIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iUmVzdWx0X0N0aSIgQWxpYXM9Iue7vOWQiOWOi+e8qeezu+aVsCIgICBVbml0PSIxL01QYSIgRGVmYXVsdD0iMC4wMDEiICBNYXg9IjEwIiAgICBNaW49IjFlLTMwIiBEaWdpdD0iMTAiIFNjaWVudGlmaWM9IjEiIERlc2M9InJlc3VsdCB0b3RhbCBjb21wcmVzc2liaWxpdHkiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IlJlc3VsdF9DZiIgIEFsaWFzPSLlsqnnn7PljovnvKnns7vmlbAiICAgVW5pdD0iMS9NUGEiIERlZmF1bHQ9IjAuMDAwMSIgTWF4PSIxMCIgICAgTWluPSIxZS0zMCIgRGlnaXQ9IjEwIiBTY2llbnRpZmljPSIxIiBEZXNjPSJyZXN1bHQgcm9jayBjb21wcmVzc2liaWxpdHkiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IlJlc3VsdF9Tb2kiIEFsaWFzPSLliJ3lp4vlkKvmsrnppbHlkozluqYiIFVuaXQ9IiIgICAgICBEZWZhdWx0PSIwLjgiICAgIE1heD0iMSIgICAgIE1pbj0iMCIgICAgIERpZ2l0PSI2IiAgRGVzYz0icmVzdWx0IGluaXRpYWwgb2lsIHNhdHVyYXRpb24iIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IlJlc3VsdF9TZ2kiIEFsaWFzPSLliJ3lp4vlkKvmsJTppbHlkozluqYiIFVuaXQ9IiIgICAgICBEZWZhdWx0PSIwIiAgICAgIE1heD0iMSIgICAgIE1pbj0iMCIgICAgIERpZ2l0PSI2IiAgRGVzYz0icmVzdWx0IGluaXRpYWwgZ2FzIHNhdHVyYXRpb24iIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IlJlc3VsdF9Td2kiIEFsaWFzPSLliJ3lp4vlkKvmsLTppbHlkozluqYiIFVuaXQ9IiIgICAgICBEZWZhdWx0PSIwLjIiICAgIE1heD0iMSIgICAgIE1pbj0iMCIgICAgIERpZ2l0PSI2IiAgRGVzYz0icmVzdWx0IGluaXRpYWwgd2F0ZXIgc2F0dXJhdGlvbiIgLz4NCg0KICAgIDxQYXJhSXRlbSBOYW1lPSJSZXN1bHRfQm8iICAgQWxpYXM9IuayueS9k+enr+ezu+aVsCIgVW5pdD0iIiAgICAgIERlZmF1bHQ9IjEiIE1heD0iMWUrMzAiIE1pbj0iMCIgICAgIERpZ2l0PSI2IiAgRGVzYz0icmVzdWx0IG9pbCBmb3JtYXRpb24gdm9sdW1lIGZhY3RvciIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iUmVzdWx0X01pdW8iIEFsaWFzPSLmsrnnm7jpu4/luqYiICAgVW5pdD0ibVBhLnMiIERlZmF1bHQ9IjEiIE1heD0iMWUrMzAiIE1pbj0iMWUtMzAiIERpZ2l0PSI2IiAgRGVzYz0icmVzdWx0IG9pbCB2aXNjb3NpdHkiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IlJlc3VsdF9DbyIgICBBbGlhcz0i5rK55Y6L57yp57O75pWwIiBVbml0PSIxL01QYSIgRGVmYXVsdD0iMCIgTWF4PSIxZSszMCIgTWluPSIwIiAgICBEaWdpdD0iMTAiIFNjaWVudGlmaWM9IjEiIERlc2M9InJlc3VsdCBvaWwgY29tcHJlc3NpYmlsaXR5IiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJSZXN1bHRfQnciICAgQWxpYXM9IuawtOS9k+enr+ezu+aVsCIgVW5pdD0ibTMvbTMiIERlZmF1bHQ9IjEiIE1heD0iMWUrMzAiIE1pbj0iMCIgICAgIERpZ2l0PSI2IiAgRGVzYz0icmVzdWx0IHdhdGVyIGZvcm1hdGlvbiB2b2x1bWUgZmFjdG9yIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJSZXN1bHRfTWl1dyIgQWxpYXM9IuawtOebuOm7j+W6piIgICBVbml0PSJtUGEucyIgRGVmYXVsdD0iMSIgTWF4PSIxZSszMCIgTWluPSIxZS0zMCIgRGlnaXQ9IjYiICBEZXNjPSJyZXN1bHQgd2F0ZXIgdmlzY29zaXR5IiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJSZXN1bHRfQ3ciICAgQWxpYXM9IuawtOWOi+e8qeezu+aVsCIgVW5pdD0iMS9NUGEiIERlZmF1bHQ9IjAiIE1heD0iMWUrMzAiIE1pbj0iMCIgICAgRGlnaXQ9IjEwIiBTY2llbnRpZmljPSIxIiBEZXNjPSJyZXN1bHQgd2F0ZXIgY29tcHJlc3NpYmlsaXR5IiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJSZXN1bHRfQmciICAgQWxpYXM9IuawlOS9k+enr+ezu+aVsCIgVW5pdD0ibTMvbTMiIERlZmF1bHQ9IjEiIE1heD0iMWUrMzAiIE1pbj0iMCIgICAgIERpZ2l0PSI2IiAgRGVzYz0icmVzdWx0IGdhcyBmb3JtYXRpb24gdm9sdW1lIGZhY3RvciIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iUmVzdWx0X01pdWciIEFsaWFzPSLmsJTnm7jpu4/luqYiICAgVW5pdD0ibVBhLnMiIERlZmF1bHQ9IjEiIE1heD0iMWUrMzAiIE1pbj0iMWUtMzAiIERpZ2l0PSI2IiAgRGVzYz0icmVzdWx0IGdhcyB2aXNjb3NpdHkiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IlJlc3VsdF9DZyIgICBBbGlhcz0i5rCU5Y6L57yp57O75pWwIiBVbml0PSIxL01QYSIgRGVmYXVsdD0iMCIgTWF4PSIxZSszMCIgTWluPSIwIiAgICBEaWdpdD0iMTAiIFNjaWVudGlmaWM9IjEiIERlc2M9InJlc3VsdCBnYXMgY29tcHJlc3NpYmlsaXR5IiAvPg0KICA8L1BhcmFHcm91cD4NCg0KICA8IS0tIOaVj+aEn+aAp+e7k+aenOaMiemYiOWAvOetm+mAieWQjuaYvuekuu+8jOepuuetm+mAieS4jeWIm+W7uuWPguaVsOS4iuS4i+mZkOihjOOAgiAtLT4NCiAgPFBhcmFHcm91cCBOYW1lPSIiIEFsaWFzPSLnu5Pmnpzlj4LmlbAiPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJTZW5zaXRpdml0eV9SdW5Db3VudCIgQWxpYXM9IuiSmeeJueWNoea0m+i/kOihjOasoeaVsCIgVW5pdD0iIiBEZWZhdWx0PSIwIiBNYXg9IjFlKzMwIiBNaW49IjAiIERpZ2l0PSIwIiBEZXNjPSLokpnnibnljaHmtJvov5DooYzmrKHmlbAiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IlNlbnNpdGl2aXR5X1RocmVzaG9sZCIgQWxpYXM9IumYiOWAvCIgVW5pdD0iTVBhIiBEZWZhdWx0PSIwIiBNYXg9IjFlKzMwIiBNaW49IjAiIERpZ2l0PSI2IiBEZXNjPSLmi5/lkIjkvJjluqbnrZvpgInpmIjlgLwiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IlNlbnNpdGl2aXR5X1NraW5fTG93ZXIiIEFsaWFzPSLooajnmq7ns7vmlbAgLSDkuIvpmZAiIFVuaXQ9IiIgRGVmYXVsdD0iMCIgTWF4PSIxMDAwIiBNaW49Ii0xMDAiIERpZ2l0PSI2IiBEZXNjPSLnrZvpgInlkI7ooajnmq7ns7vmlbDkuIvpmZAiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IlNlbnNpdGl2aXR5X1NraW5fSGlnaGVyIiBBbGlhcz0i6KGo55qu57O75pWwIC0g5LiK6ZmQIiBVbml0PSIiIERlZmF1bHQ9IjAiIE1heD0iMTAwMCIgTWluPSItMTAwIiBEaWdpdD0iNiIgRGVzYz0i562b6YCJ5ZCO6KGo55qu57O75pWw5LiK6ZmQIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJTZW5zaXRpdml0eV9DX0xvd2VyIiBBbGlhcz0i5LqV562S5YKo6ZuG57O75pWwIC0g5LiL6ZmQIiBVbml0PSJtXjMvTVBhIiBEZWZhdWx0PSIwIiBNYXg9IjEwMDAiIE1pbj0iMCIgRGlnaXQ9IjYiIERlc2M9Iuetm+mAieWQjuS6leetkuWCqOmbhuezu+aVsOS4i+mZkCIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iU2Vuc2l0aXZpdHlfQ19IaWdoZXIiIEFsaWFzPSLkupXnrZLlgqjpm4bns7vmlbAgLSDkuIrpmZAiIFVuaXQ9Im1eMy9NUGEiIERlZmF1bHQ9IjAiIE1heD0iMTAwMCIgTWluPSIwIiBEaWdpdD0iNiIgRGVzYz0i562b6YCJ5ZCO5LqV562S5YKo6ZuG57O75pWw5LiK6ZmQIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJTZW5zaXRpdml0eV9QaV9Mb3dlciIgQWxpYXM9IuWIneWni+WcsOWxguWOi+WKmyAtIOS4i+mZkCIgVW5pdD0iTVBhIiBEZWZhdWx0PSI0MCIgTWF4PSI1MDAiIE1pbj0iMC4xIiBEaWdpdD0iNiIgRGVzYz0i562b6YCJ5ZCO5Yid5aeL5Zyw5bGC5Y6L5Yqb5LiL6ZmQIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJTZW5zaXRpdml0eV9QaV9IaWdoZXIiIEFsaWFzPSLliJ3lp4vlnLDlsYLljovlipsgLSDkuIrpmZAiIFVuaXQ9Ik1QYSIgRGVmYXVsdD0iNDAiIE1heD0iNTAwIiBNaW49IjAuMSIgRGlnaXQ9IjYiIERlc2M9Iuetm+mAieWQjuWIneWni+WcsOWxguWOi+WKm+S4iumZkCIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iU2Vuc2l0aXZpdHlfS19Mb3dlciIgQWxpYXM9Iua4l+mAj+eOhyAtIOS4i+mZkCIgVW5pdD0ibUQiIERlZmF1bHQ9IjI1IiBNYXg9IjEwMDAwIiBNaW49IjAiIERpZ2l0PSI2IiBEZXNjPSLnrZvpgInlkI7muJfpgI/njofkuIvpmZAiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IlNlbnNpdGl2aXR5X0tfSGlnaGVyIiBBbGlhcz0i5riX6YCP546HIC0g5LiK6ZmQIiBVbml0PSJtRCIgRGVmYXVsdD0iMjUiIE1heD0iMTAwMDAiIE1pbj0iMCIgRGlnaXQ9IjYiIERlc2M9Iuetm+mAieWQjua4l+mAj+eOh+S4iumZkCIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iU2Vuc2l0aXZpdHlfaF9Mb3dlciIgQWxpYXM9IuWCqOWxguWOmuW6piAtIOS4i+mZkCIgVW5pdD0ibSIgRGVmYXVsdD0iMTAiIE1heD0iMTAwMDAiIE1pbj0iMWUtMDUiIERpZ2l0PSI2IiBEZXNjPSLnrZvpgInlkI7lgqjlsYLljprluqbkuIvpmZAiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IlNlbnNpdGl2aXR5X2hfSGlnaGVyIiBBbGlhcz0i5YKo5bGC5Y6a5bqmIC0g5LiK6ZmQIiBVbml0PSJtIiBEZWZhdWx0PSIxMCIgTWF4PSIxMDAwMCIgTWluPSIxZS0wNSIgRGlnaXQ9IjYiIERlc2M9Iuetm+mAieWQjuWCqOWxguWOmuW6puS4iumZkCIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iU2Vuc2l0aXZpdHlfcGhpX0xvd2VyIiBBbGlhcz0i5a2U6ZqZ5bqmIC0g5LiL6ZmQIiBVbml0PSIiIERlZmF1bHQ9IjAuMSIgTWF4PSIxIiBNaW49IjFlLTA1IiBEaWdpdD0iNiIgRGVzYz0i562b6YCJ5ZCO5a2U6ZqZ5bqm5LiL6ZmQIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJTZW5zaXRpdml0eV9waGlfSGlnaGVyIiBBbGlhcz0i5a2U6ZqZ5bqmIC0g5LiK6ZmQIiBVbml0PSIiIERlZmF1bHQ9IjAuMSIgTWF4PSIxIiBNaW49IjFlLTA1IiBEaWdpdD0iNiIgRGVzYz0i562b6YCJ5ZCO5a2U6ZqZ5bqm5LiK6ZmQIiAvPg0KICAgIDwhLS0g56ys5Zub56eN77ya5oyJ5ZCM5LiA6K+v5beu6ZiI5YC8562b6YCJ5ZCE57uE5ouf5ZCI5pyA5LyY5YC844CCIC0tPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJTZW5zaXRpdml0eV9GaXRfS19NaW5pbXVtIiBBbGlhcz0i5riX6YCP546HIC0g5pyA5bCP5YC8IiBVbml0PSJtRCIgRGVmYXVsdD0iMjUiIE1heD0iMTAwMDAiIE1pbj0iMCIgRGlnaXQ9IjYiIERlc2M9Iuetm+mAieWQjuaLn+WQiOWPguaVsOa4l+mAj+eOh+acgOWwj+WAvCIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iU2Vuc2l0aXZpdHlfRml0X0tfTWF4aW11bSIgQWxpYXM9Iua4l+mAj+eOhyAtIOacgOWkp+WAvCIgVW5pdD0ibUQiIERlZmF1bHQ9IjI1IiBNYXg9IjEwMDAwIiBNaW49IjAiIERpZ2l0PSI2IiBEZXNjPSLnrZvpgInlkI7mi5/lkIjlj4LmlbDmuJfpgI/njofmnIDlpKflgLwiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IlNlbnNpdGl2aXR5X0ZpdF9Ta2luX01pbmltdW0iIEFsaWFzPSLooajnmq7ns7vmlbAgLSDmnIDlsI/lgLwiIFVuaXQ9IiIgRGVmYXVsdD0iMCIgTWF4PSIxMDAwIiBNaW49Ii0xMDAiIERpZ2l0PSI2IiBEZXNjPSLnrZvpgInlkI7mi5/lkIjlj4LmlbDooajnmq7ns7vmlbDmnIDlsI/lgLwiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IlNlbnNpdGl2aXR5X0ZpdF9Ta2luX01heGltdW0iIEFsaWFzPSLooajnmq7ns7vmlbAgLSDmnIDlpKflgLwiIFVuaXQ9IiIgRGVmYXVsdD0iMCIgTWF4PSIxMDAwIiBNaW49Ii0xMDAiIERpZ2l0PSI2IiBEZXNjPSLnrZvpgInlkI7mi5/lkIjlj4LmlbDooajnmq7ns7vmlbDmnIDlpKflgLwiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IlNlbnNpdGl2aXR5X0ZpdF9DX01pbmltdW0iIEFsaWFzPSLkupXnrZLlgqjpm4bns7vmlbAgLSDmnIDlsI/lgLwiIFVuaXQ9Im1eMy9NUGEiIERlZmF1bHQ9IjAiIE1heD0iMTAwMCIgTWluPSIwIiBEaWdpdD0iNiIgRGVzYz0i562b6YCJ5ZCO5ouf5ZCI5Y+C5pWw5LqV562S5YKo6ZuG57O75pWw5pyA5bCP5YC8IiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJTZW5zaXRpdml0eV9GaXRfQ19NYXhpbXVtIiBBbGlhcz0i5LqV562S5YKo6ZuG57O75pWwIC0g5pyA5aSn5YC8IiBVbml0PSJtXjMvTVBhIiBEZWZhdWx0PSIwIiBNYXg9IjEwMDAiIE1pbj0iMCIgRGlnaXQ9IjYiIERlc2M9Iuetm+mAieWQjuaLn+WQiOWPguaVsOS6leetkuWCqOmbhuezu+aVsOacgOWkp+WAvCIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iU2Vuc2l0aXZpdHlfRml0X3BoaV9NaW5pbXVtIiBBbGlhcz0i5a2U6ZqZ5bqmIC0g5pyA5bCP5YC8IiBVbml0PSIiIERlZmF1bHQ9IjAuMSIgTWF4PSIxIiBNaW49IjFlLTA1IiBEaWdpdD0iNiIgRGVzYz0i562b6YCJ5ZCO5ouf5ZCI5Y+C5pWw5a2U6ZqZ5bqm5pyA5bCP5YC8IiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJTZW5zaXRpdml0eV9GaXRfcGhpX01heGltdW0iIEFsaWFzPSLlrZTpmpnluqYgLSDmnIDlpKflgLwiIFVuaXQ9IiIgRGVmYXVsdD0iMC4xIiBNYXg9IjEiIE1pbj0iMWUtMDUiIERpZ2l0PSI2IiBEZXNjPSLnrZvpgInlkI7mi5/lkIjlj4LmlbDlrZTpmpnluqbmnIDlpKflgLwiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IlNlbnNpdGl2aXR5X0ZpdF9EZmNfTWluaW11bSIgQWxpYXM9Iuijgue8neWvvOa1geiDveWKmyAtIOacgOWwj+WAvCIgVW5pdD0ibUQubSIgRGVmYXVsdD0iMTAwMCIgTWF4PSIxZSszMCIgTWluPSIwIiBEaWdpdD0iNiIgRGVzYz0i562b6YCJ5ZCO5ouf5ZCI5Y+C5pWw6KOC57yd5a+85rWB6IO95Yqb5pyA5bCP5YC8IiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJTZW5zaXRpdml0eV9GaXRfRGZjX01heGltdW0iIEFsaWFzPSLoo4LnvJ3lr7zmtYHog73lipsgLSDmnIDlpKflgLwiIFVuaXQ9Im1ELm0iIERlZmF1bHQ9IjEwMDAiIE1heD0iMWUrMzAiIE1pbj0iMCIgRGlnaXQ9IjYiIERlc2M9Iuetm+mAieWQjuaLn+WQiOWPguaVsOijgue8neWvvOa1geiDveWKm+acgOWkp+WAvCIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iU2Vuc2l0aXZpdHlfRml0X0ZyYWN0dXJlSGFsZkxlbmd0aF9NaW5pbXVtIiBBbGlhcz0i6KOC57yd5Y2K6ZW/IC0g5pyA5bCP5YC8IiBVbml0PSJtIiBEZWZhdWx0PSI1MCIgTWF4PSIxMDAwMCIgTWluPSIxZS0wNSIgRGlnaXQ9IjYiIERlc2M9Iuetm+mAieWQjuaLn+WQiOWPguaVsOijgue8neWNiumVv+acgOWwj+WAvCIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iU2Vuc2l0aXZpdHlfRml0X0ZyYWN0dXJlSGFsZkxlbmd0aF9NYXhpbXVtIiBBbGlhcz0i6KOC57yd5Y2K6ZW/IC0g5pyA5aSn5YC8IiBVbml0PSJtIiBEZWZhdWx0PSI1MCIgTWF4PSIxMDAwMCIgTWluPSIxZS0wNSIgRGlnaXQ9IjYiIERlc2M9Iuetm+mAieWQjuaLn+WQiOWPguaVsOijgue8neWNiumVv+acgOWkp+WAvCIgLz4NCiAgPC9QYXJhR3JvdXA+DQoNCjwvUm9vdD4NCg== \ No newline at end of file diff --git a/Bin/Config/Common/ModelParaDefinesNM_en.dat b/Bin/Config/Common/ModelParaDefinesNM_en.dat index c1bdf599..f6be0ef6 100644 --- a/Bin/Config/Common/ModelParaDefinesNM_en.dat +++ b/Bin/Config/Common/ModelParaDefinesNM_en.dat @@ -1 +1 @@ -77u/PD94bWwgcup_mpadmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4NCg0KPCEtLSoqKioqKioqKiwzyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiotLT4NCjwhLS0gICAgVGhpcyBmaWxlIGRlZmluZXMgcGFyYW1ldGVycyBmb3IgdGhlIFdUQUkgTnVtZXJpY2FsIChOTSkgICAgLS0+DQo8IS0tICAgIG1vZHVsZS4gT25seSByZXNlcnZvaXIsIHdlbGwsIGFuZCBnZW9tZXRyeSBwYXJhbWV0ZXJzICAgICAgICAtLT4NCjwhLS0gICAgcmVxdWlyZWQgYnkgdGhlIFBFQkkgc29sdmVyIGFyZSBpbmNsdWRlZC4gICAgICAgICAgICAgICAgICAgIC0tPg0KPCEtLSAgICBEYXRlOiAyMDI2MDYxNSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLS0+DQo8IS0tKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi0tPg0KDQo8IS0tDQogICAgUGFyYW1ldGVyIHNjb3BlOiByZXNlcnZvaXIsIHdlbGwsIGFuZCBnZW9tZXRyeSBwYXJhbWV0ZXJzIHJlcXVpcmVkIGJ5IHRoZSBQRUJJIHNvbHZlcg0KICAgIENvcnJlc3BvbmRzIHRvIEhYX05XVE1fTU9ERUxfSU5QVVQgc3RydWN0IGZpZWxkcw0KICAgIExvYWRlZCB2aWEgX3BhcmFIZWxwZXItPmxvYWRQYXJhRGVmaW5lcygpLCBzS2V5ID0gc19ObV9TZXJpZQ0KLS0+DQoNCjxSb290Pg0KDQogIDxQYXJhR3JvdXAgTmFtZT0iIiBBbGlhcz0iVGltZSBTdGVwIFNldHRpbmdzIj4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iTk1fVGltZUdyb3d0aEV4cG9uZW50IiBBbGlhcz0iVGltZSBHcm93dGggRXhwb25lbnQiIFVuaXQ9IiIgIERlZmF1bHQ9IjEuMDUiICAgTWF4PSIxMCIgICAgTWluPSIxIiAgICAgRGlnaXQ9IjYiIERlc2M9InRpbWUgZ3Jvd3RoIGV4cG9uZW50IiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJOTV9EdE1pbiIgICAgICAgICAgICAgIEFsaWFzPSJNaW5pbXVtIFRpbWUgU3RlcCIgICAgVW5pdD0iaHIiIERlZmF1bHQ9IjAuMDAyNSIgTWF4PSIxZSszMCIgTWluPSIxZS0xMiIgRGlnaXQ9IjYiIERlc2M9Im1pbmltdW0gdGltZSBzdGVwIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJOTV9EdE1heCIgICAgICAgICAgICAgIEFsaWFzPSJNYXhpbXVtIFRpbWUgU3RlcCIgICAgVW5pdD0iaHIiIERlZmF1bHQ9IjEyLjUiICAgTWF4PSIxZSszMCIgTWluPSIxZS0xMiIgRGlnaXQ9IjYiIERlc2M9Im1heGltdW0gdGltZSBzdGVwIiAvPg0KICA8L1BhcmFHcm91cD4NCg0KICA8UGFyYUdyb3VwIE5hbWU9IiIgQWxpYXM9IlJlc2Vydm9pciBQYXJhbWV0ZXJzIj4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iaCIgICBBbGlhcz0iUmVzZXJ2b2lyIFRoaWNrbmVzcyIgICAgICAgICBVbml0PSJtIiAgICAgRGVmYXVsdD0iMTAiICAgIE1heD0iMTAwMDAiICBNaW49IjFlLTA1IiAgRGlnaXQ9IjMiICBEZXNjPSJyZXNlcnZvaXIgdGhpY2tuZXNzIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJQaSIgIEFsaWFzPSJJbml0aWFsIFByZXNzdXJlIiAgICAgICAgICAgIFVuaXQ9Ik1QYSIgICBEZWZhdWx0PSI0MCIgICAgTWF4PSI1MDAiICAgIE1pbj0iMC4xIiAgICBEaWdpdD0iNSIgIERlc2M9ImluaXRpYWwgZm9ybWF0aW9uIHByZXNzdXJlIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJLIiAgIEFsaWFzPSJQZXJtZWFiaWxpdHkiICAgICAgICAgICAgICAgIFVuaXQ9Im1EIiAgICBEZWZhdWx0PSIyNSIgICAgTWF4PSIxMDAwMCIgIE1pbj0iMCIgICAgICBEaWdpdD0iNiIgIERlc2M9InBlcm1lYWJpbGl0eSIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0icGhpIiBBbGlhcz0iUG9yb3NpdHkiICAgICAgICAgICAgICAgICAgICBVbml0PSIiICAgICAgRGVmYXVsdD0iMC4xIiAgIE1heD0iMSIgICAgICBNaW49IjFlLTA1IiAgRGlnaXQ9IjQiICBEZXNjPSJwb3Jvc2l0eSIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iQm8iICBBbGlhcz0iT2lsIEZvcm1hdGlvbiBWb2x1bWUgRmFjdG9yIiBVbml0PSIiICAgICAgRGVmYXVsdD0iMS4yIiAgIE1heD0iMTAiICAgICBNaW49IjFlLTA2IiAgRGlnaXQ9IjYiICBEZXNjPSJvaWwgZm9ybWF0aW9uIHZvbHVtZSBmYWN0b3IiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9Ik1pdW8iIEFsaWFzPSJPaWwgVmlzY29zaXR5IiAgICAgICAgICAgICAgVW5pdD0ibVBhLnMiIERlZmF1bHQ9IjAuNSIgICBNYXg9IjEwMDAwIiAgTWluPSIxZS0wNiIgIERpZ2l0PSI2IiAgRGVzYz0ib2lsIHZpc2Nvc2l0eSIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iQnciICBBbGlhcz0iV2F0ZXIgRm9ybWF0aW9uIFZvbHVtZSBGYWN0b3IiIFVuaXQ9IiIgICAgRGVmYXVsdD0iMSIgICAgIE1heD0iMTAiICAgICBNaW49IjFlLTA2IiAgRGlnaXQ9IjYiICBEZXNjPSJ3YXRlciBmb3JtYXRpb24gdm9sdW1lIGZhY3RvciIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iTWl1dyIgQWxpYXM9IldhdGVyIFZpc2Nvc2l0eSIgICAgICAgICAgICBVbml0PSJtUGEucyIgRGVmYXVsdD0iMSIgICAgIE1heD0iMTAwMDAiICBNaW49IjFlLTA2IiAgRGlnaXQ9IjYiICBEZXNjPSJ3YXRlciB2aXNjb3NpdHkiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IkN0aSIgQWxpYXM9IlRvdGFsIENvbXByZXNzaWJpbGl0eSIgICAgICAgVW5pdD0iMS9NUGEiIERlZmF1bHQ9IjAuMDAxIiBNYXg9IjEwIiAgICAgTWluPSIxZS0zMCIgIERpZ2l0PSIxMCIgU2NpZW50aWZpYz0iMSIgRGVzYz0idG90YWwgY29tcHJlc3NpYmlsaXR5IiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJDZiIgIEFsaWFzPSJSb2NrIENvbXByZXNzaWJpbGl0eSIgICAgICAgIFVuaXQ9IjEvTVBhIiBEZWZhdWx0PSIwLjAwMDEiIE1heD0iMTAiICAgIE1pbj0iMWUtMzAiICBEaWdpdD0iMTAiIFNjaWVudGlmaWM9IjEiIERlc2M9InJvY2sgY29tcHJlc3NpYmlsaXR5IiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJTb2kiIEFsaWFzPSJJbml0aWFsIE9pbCBTYXR1cmF0aW9uIiAgICAgIFVuaXQ9IiIgICAgICBEZWZhdWx0PSIwLjgiICAgTWF4PSIxIiAgICAgIE1pbj0iMCIgICAgICBEaWdpdD0iNiIgIERlc2M9ImluaXRpYWwgb2lsIHNhdHVyYXRpb24iIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IlNnaSIgQWxpYXM9IkluaXRpYWwgR2FzIFNhdHVyYXRpb24iICAgICAgVW5pdD0iIiAgICAgIERlZmF1bHQ9IjAiICAgICBNYXg9IjEiICAgICAgTWluPSIwIiAgICAgIERpZ2l0PSI2IiAgRGVzYz0iaW5pdGlhbCBnYXMgc2F0dXJhdGlvbiIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iU3dpIiBBbGlhcz0iSW5pdGlhbCBXYXRlciBTYXR1cmF0aW9uIiAgICBVbml0PSIiICAgICAgRGVmYXVsdD0iMC4yIiAgIE1heD0iMSIgICAgICBNaW49IjAiICAgICAgRGlnaXQ9IjYiICBEZXNjPSJpbml0aWFsIHdhdGVyIHNhdHVyYXRpb24iIC8+DQogIDwvUGFyYUdyb3VwPg0KDQogIDxQYXJhR3JvdXAgTmFtZT0iIiBBbGlhcz0iV2VsbCBQYXJhbWV0ZXJzIj4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iV19YIiAgICBBbGlhcz0iWCBDb29yZGluYXRlIiAgICAgICAgICAgIFVuaXQ9Im0iICAgICAgRGVmYXVsdD0iMCIgICAgIE1heD0iMTAwMDAiICBNaW49Ii0xMDAwMCIgRGlnaXQ9IjYiICBEZXNjPSJ3ZWxsIFggY29vcmRpbmF0ZSIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iV19ZIiAgICBBbGlhcz0iWSBDb29yZGluYXRlIiAgICAgICAgICAgIFVuaXQ9Im0iICAgICAgRGVmYXVsdD0iMCIgICAgIE1heD0iMTAwMDAiICBNaW49Ii0xMDAwMCIgRGlnaXQ9IjYiICBEZXNjPSJ3ZWxsIFkgY29vcmRpbmF0ZSIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iV19SdyIgICBBbGlhcz0iV2VsbGJvcmUgUmFkaXVzIiAgICAgICAgIFVuaXQ9Im0iICAgICAgRGVmYXVsdD0iMC4xIiAgIE1heD0iMTAiICAgICBNaW49IjAuMDAxIiAgRGlnaXQ9IjYiICBEZXNjPSJ3ZWxsYm9yZSByYWRpdXMiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IldfU2tpbiIgQWxpYXM9IlNraW4gRmFjdG9yIiAgICAgICAgICAgICBVbml0PSIiICAgICAgIERlZmF1bHQ9IjAiICAgICBNYXg9IjEwMDAiICAgTWluPSItMTAwIiAgIERpZ2l0PSI2IiAgRGVzYz0ic2tpbiBmYWN0b3IiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IldfQyIgICAgQWxpYXM9IldlbGxib3JlIFN0b3JhZ2UgQ29lZmYiICBVbml0PSJtXjMvTVBhIiBEZWZhdWx0PSIwIiAgICAgTWF4PSIxMDAwIiAgIE1pbj0iMCIgICAgICBEaWdpdD0iNiIgIERlc2M9IndlbGxib3JlIHN0b3JhZ2UgY29lZmZpY2llbnQiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IldfQm90dG9taG9sZU1EIiAgICAgICBBbGlhcz0iQm90dG9taG9sZSBNRCIgICAgICAgICAgVW5pdD0ibSIgICAgRGVmYXVsdD0iNjAwMCIgTWF4PSIxMDAwMDAiIE1pbj0iMCIgICAgIERpZ2l0PSI2IiBEZXNjPSJib3R0b21ob2xlIG1lYXN1cmVkIGRlcHRoIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJXX1dlbGxMZW5ndGgiICAgICAgICAgQWxpYXM9IldlbGwgTGVuZ3RoIiAgICAgICAgICAgIFVuaXQ9Im0iICAgIERlZmF1bHQ9IjIwMCIgIE1heD0iMTAwMDAiICBNaW49IjFlLTA1IiBEaWdpdD0iNiIgRGVzYz0id2VsbGJvcmUgbGVuZ3RoIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJXX1BlcmZvcmF0aW9uTWRTdGFydCIgQWxpYXM9IlBlcmZvcmF0aW9uIFN0YXJ0IE1EIiAgIFVuaXQ9Im0iICAgIERlZmF1bHQ9IjYwMDAiIE1heD0iMTAwMDAwIiBNaW49IjAiICAgICBEaWdpdD0iNiIgRGVzYz0icGVyZm9yYXRpb24gc3RhcnQgbWVhc3VyZWQgZGVwdGgiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IldfUGVyZm9yYXRpb25NZEVuZCIgICBBbGlhcz0iUGVyZm9yYXRpb24gRW5kIE1EIiAgICAgVW5pdD0ibSIgICAgRGVmYXVsdD0iNjAzMCIgTWF4PSIxMDAwMDAiIE1pbj0iMCIgICAgIERpZ2l0PSI2IiBEZXNjPSJwZXJmb3JhdGlvbiBlbmQgbWVhc3VyZWQgZGVwdGgiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IldfRHJhaW5BbmdsZSIgICAgICAgICBBbGlhcz0iRHJhaW4gQW5nbGUiICAgICAgICAgICAgVW5pdD0iZGVnIiAgRGVmYXVsdD0iMCIgICAgTWF4PSIzNjAiICAgTWluPSItMzYwIiAgRGlnaXQ9IjYiIERlc2M9Imhvcml6b250YWwgd2VsbCBkcmFpbiBhbmdsZSIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iV19OdW1iZXJPZkZyYWN0dXJlcyIgIEFsaWFzPSJOdW1iZXIgb2YgRnJhY3R1cmVzIiAgICBVbml0PSIiICAgICBEZWZhdWx0PSIxNSIgICBNYXg9IjEwMDAiICBNaW49IjIiICAgICBEaWdpdD0iMCIgRGVzYz0ibnVtYmVyIG9mIGZyYWN0dXJlcyIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iV19GcmFjdHVyZUhhbGZMZW5ndGgiIEFsaWFzPSJGcmFjdHVyZSBIYWxmLUxlbmd0aCIgICBVbml0PSJtIiAgICBEZWZhdWx0PSI1MCIgICBNYXg9IjEwMDAwIiBNaW49IjFlLTA1IiBEaWdpdD0iNiIgRGVzYz0iZnJhY3R1cmUgaGFsZi1sZW5ndGgiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IldfRnJhY3R1cmVBbmdsZSIgICAgICBBbGlhcz0iRnJhY3R1cmUgQW5nbGUiICAgICAgICAgVW5pdD0iZGVnIiAgRGVmYXVsdD0iOTAiICAgTWF4PSIzNjAiICAgTWluPSItMzYwIiAgRGlnaXQ9IjYiIERlc2M9ImZyYWN0dXJlIGFuZ2xlIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJXX0ZyYWN0dXJlSGVpZ2h0IiAgICAgQWxpYXM9IkZyYWN0dXJlIEhlaWdodCIgICAgICAgIFVuaXQ9Im0iICAgIERlZmF1bHQ9IjEwIiAgIE1heD0iMTAwMDAiIE1pbj0iMWUtMDUiIERpZ2l0PSI2IiBEZXNjPSJmcmFjdHVyZSBoZWlnaHQiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IldfRnJhY3R1cmVNaWRQb2ludEhlaWdodCIgQWxpYXM9IkZyYWN0dXJlIE1pZHBvaW50IEhlaWdodCIgVW5pdD0ibSIgRGVmYXVsdD0iNSIgTWF4PSIxMDAwMCIgTWluPSIwIiBEaWdpdD0iNiIgRGVzYz0iZnJhY3R1cmUgbWlkcG9pbnQgaGVpZ2h0IiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJXX0ZyYWN0dXJlV2lkdGgiICAgICAgQWxpYXM9IkZyYWN0dXJlIFdpZHRoIiAgICAgICAgIFVuaXQ9Im0iICAgIERlZmF1bHQ9IjAuMDAxIiBNYXg9IjEwMCIgIE1pbj0iMWUtMDgiIERpZ2l0PSI4IiBEZXNjPSJmcmFjdHVyZSB3aWR0aCIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iV19EZmMiICAgICAgICAgICAgICAgIEFsaWFzPSJGcmFjdHVyZSBDb25kdWN0aXZpdHkiICBVbml0PSJtRC5tIiBEZWZhdWx0PSIxMDAwIiBNYXg9IjFlKzMwIiBNaW49IjAiICAgICBEaWdpdD0iNiIgRGVzYz0iZnJhY3R1cmUgY29uZHVjdGl2aXR5IiAvPg0KICA8L1BhcmFHcm91cD4NCg0KICA8UGFyYUdyb3VwIE5hbWU9IiIgQWxpYXM9IkluZGVwZW5kZW50IEZyYWN0dXJlIFBhcmFtZXRlcnMiPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJGX1gwIiBBbGlhcz0iU3RhcnQgWDAiICAgICAgICAgICAgICBVbml0PSJtIiAgICBEZWZhdWx0PSIwIiBNYXg9IjEwMDAwIiBNaW49Ii0xMDAwMCIgRGlnaXQ9IjYiIERlc2M9ImZyYWN0dXJlIHN0YXJ0IFggY29vcmRpbmF0ZSIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iRl9ZMCIgQWxpYXM9IlN0YXJ0IFkwIiAgICAgICAgICAgICAgVW5pdD0ibSIgICAgRGVmYXVsdD0iMCIgTWF4PSIxMDAwMCIgTWluPSItMTAwMDAiIERpZ2l0PSI2IiBEZXNjPSJmcmFjdHVyZSBzdGFydCBZIGNvb3JkaW5hdGUiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IkZfWDEiIEFsaWFzPSJFbmQgWDEiICAgICAgICAgICAgICAgIFVuaXQ9Im0iICAgIERlZmF1bHQ9IjAiIE1heD0iMTAwMDAiIE1pbj0iLTEwMDAwIiBEaWdpdD0iNiIgRGVzYz0iZnJhY3R1cmUgZW5kIFggY29vcmRpbmF0ZSIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iRl9ZMSIgQWxpYXM9IkVuZCBZMSIgICAgICAgICAgICAgICAgVW5pdD0ibSIgICAgRGVmYXVsdD0iMCIgTWF4PSIxMDAwMCIgTWluPSItMTAwMDAiIERpZ2l0PSI2IiBEZXNjPSJmcmFjdHVyZSBlbmQgWSBjb29yZGluYXRlIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJGX0ZDIiBBbGlhcz0iRnJhY3R1cmUgQ29uZHVjdGl2aXR5IiBVbml0PSJtRC5tIiBEZWZhdWx0PSIxIiBNYXg9IjFlKzMwIiBNaW49IjAiICAgICAgRGlnaXQ9IjYiIERlc2M9ImZyYWN0dXJlIGNvbmR1Y3Rpdml0eSIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iRl9EVyIgQWxpYXM9IkZyYWN0dXJlIFdpZHRoIFBhcmFtZXRlciIgVW5pdD0iIiBEZWZhdWx0PSIxIiBNYXg9IjFlKzMwIiBNaW49IjAiIERpZ2l0PSI2IiBEZXNjPSJmcmFjdHVyZSB3aWR0aCBwYXJhbWV0ZXIiIC8+DQogIDwvUGFyYUdyb3VwPg0KDQogIDxQYXJhR3JvdXAgTmFtZT0iIiBBbGlhcz0iRmF1bHQgUGFyYW1ldGVycyI+DQogICAgPFBhcmFJdGVtIE5hbWU9IkZUX1gwIiBBbGlhcz0iU3RhcnQgWDAiIFVuaXQ9Im0iIERlZmF1bHQ9IjAiIE1heD0iMTAwMDAiIE1pbj0iLTEwMDAwIiBEaWdpdD0iNiIgRGVzYz0iZmF1bHQgc3RhcnQgWCBjb29yZGluYXRlIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJGVF9ZMCIgQWxpYXM9IlN0YXJ0IFkwIiBVbml0PSJtIiBEZWZhdWx0PSIwIiBNYXg9IjEwMDAwIiBNaW49Ii0xMDAwMCIgRGlnaXQ9IjYiIERlc2M9ImZhdWx0IHN0YXJ0IFkgY29vcmRpbmF0ZSIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iRlRfWDEiIEFsaWFzPSJFbmQgWDEiIFVuaXQ9Im0iIERlZmF1bHQ9IjAiIE1heD0iMTAwMDAiIE1pbj0iLTEwMDAwIiBEaWdpdD0iNiIgRGVzYz0iZmF1bHQgZW5kIFggY29vcmRpbmF0ZSIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iRlRfWTEiIEFsaWFzPSJFbmQgWTEiIFVuaXQ9Im0iIERlZmF1bHQ9IjAiIE1heD0iMTAwMDAiIE1pbj0iLTEwMDAwIiBEaWdpdD0iNiIgRGVzYz0iZmF1bHQgZW5kIFkgY29vcmRpbmF0ZSIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iRlRfTGVha2FnZSIgQWxpYXM9IkxlYWthZ2UgQ29lZmZpY2llbnQiIFVuaXQ9IiIgRGVmYXVsdD0iMSIgTWF4PSIxZSszMCIgTWluPSIwIiBEaWdpdD0iNiIgRGVzYz0iZmF1bHQgbGVha2FnZSBjb2VmZmljaWVudCIgLz4NCiAgPC9QYXJhR3JvdXA+DQoNCiAgPFBhcmFHcm91cCBOYW1lPSIiIEFsaWFzPSJSZWN0YW5nbGUgQm91bmRhcnkgUGFyYW1ldGVycyI+DQogICAgPFBhcmFJdGVtIE5hbWU9IkJSX1hNaW4iIEFsaWFzPSJMZWZ0IEJvdW5kYXJ5IFgiIFVuaXQ9Im0iIERlZmF1bHQ9IjAiIE1heD0iMTAwMDAiIE1pbj0iLTEwMDAwIiBEaWdpdD0iNiIgRGVzYz0icmVjdGFuZ2xlIGJvdW5kYXJ5IG1pbmltdW0gWCIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iQlJfWU1pbiIgQWxpYXM9IkJvdHRvbSBCb3VuZGFyeSBZIiBVbml0PSJtIiBEZWZhdWx0PSIwIiBNYXg9IjEwMDAwIiBNaW49Ii0xMDAwMCIgRGlnaXQ9IjYiIERlc2M9InJlY3RhbmdsZSBib3VuZGFyeSBtaW5pbXVtIFkiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IkJSX1hNYXgiIEFsaWFzPSJSaWdodCBCb3VuZGFyeSBYIiBVbml0PSJtIiBEZWZhdWx0PSIwIiBNYXg9IjEwMDAwIiBNaW49Ii0xMDAwMCIgRGlnaXQ9IjYiIERlc2M9InJlY3RhbmdsZSBib3VuZGFyeSBtYXhpbXVtIFgiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IkJSX1lNYXgiIEFsaWFzPSJUb3AgQm91bmRhcnkgWSIgVW5pdD0ibSIgRGVmYXVsdD0iMCIgTWF4PSIxMDAwMCIgTWluPSItMTAwMDAiIERpZ2l0PSI2IiBEZXNjPSJyZWN0YW5nbGUgYm91bmRhcnkgbWF4aW11bSBZIiAvPg0KICA8L1BhcmFHcm91cD4NCg0KICA8UGFyYUdyb3VwIE5hbWU9IiIgQWxpYXM9IkNpcmNsZSBCb3VuZGFyeSBQYXJhbWV0ZXJzIj4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iQkNfQ2VudGVyWCIgQWxpYXM9IkNlbnRlciBYIiBVbml0PSJtIiBEZWZhdWx0PSIwIiBNYXg9IjEwMDAwIiBNaW49Ii0xMDAwMCIgRGlnaXQ9IjYiIERlc2M9ImNpcmNsZSBib3VuZGFyeSBjZW50ZXIgWCIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iQkNfQ2VudGVyWSIgQWxpYXM9IkNlbnRlciBZIiBVbml0PSJtIiBEZWZhdWx0PSIwIiBNYXg9IjEwMDAwIiBNaW49Ii0xMDAwMCIgRGlnaXQ9IjYiIERlc2M9ImNpcmNsZSBib3VuZGFyeSBjZW50ZXIgWSIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iQkNfUmFkaXVzIiAgQWxpYXM9IlJhZGl1cyIgICBVbml0PSJtIiBEZWZhdWx0PSIxIiBNYXg9IjEwMDAwIiBNaW49IjFlLTA1IiAgRGlnaXQ9IjYiIERlc2M9ImNpcmNsZSBib3VuZGFyeSByYWRpdXMiIC8+DQogIDwvUGFyYUdyb3VwPg0KDQogIDxQYXJhR3JvdXAgTmFtZT0iIiBBbGlhcz0iUG9seWdvbiBCb3VuZGFyeSBWZXJ0ZXggUGFyYW1ldGVycyI+DQogICAgPFBhcmFJdGVtIE5hbWU9IkJQX1giIEFsaWFzPSJYIENvb3JkaW5hdGUiIFVuaXQ9Im0iIERlZmF1bHQ9IjAiIE1heD0iMTAwMDAiIE1pbj0iLTEwMDAwIiBEaWdpdD0iNiIgRGVzYz0icG9seWdvbiBib3VuZGFyeSB2ZXJ0ZXggWCIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iQlBfWSIgQWxpYXM9IlkgQ29vcmRpbmF0ZSIgVW5pdD0ibSIgRGVmYXVsdD0iMCIgTWF4PSIxMDAwMCIgTWluPSItMTAwMDAiIERpZ2l0PSI2IiBEZXNjPSJwb2x5Z29uIGJvdW5kYXJ5IHZlcnRleCBZIiAvPg0KICA8L1BhcmFHcm91cD4NCg0KICA8UGFyYUdyb3VwIE5hbWU9IiIgQWxpYXM9IlJlZ2lvbiBQYXJhbWV0ZXJzIj4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iUl9MZWFrYWdlIiBBbGlhcz0iTGVha2FnZSBDb2VmZmljaWVudCIgVW5pdD0iIiBEZWZhdWx0PSIxIiBNYXg9IjFlKzMwIiBNaW49IjAiIERpZ2l0PSI2IiBEZXNjPSJyZWdpb24gbGVha2FnZSBjb2VmZmljaWVudCIgLz4NCiAgPC9QYXJhR3JvdXA+DQoNCiAgPFBhcmFHcm91cCBOYW1lPSIiIEFsaWFzPSJSZWdpb24gTWFyayBQYXJhbWV0ZXJzIj4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iUk1fQ29tVyIgICAgICAgQWxpYXM9IlN0b3JhZ2UgUmF0aW8iIFVuaXQ9IiIgRGVmYXVsdD0iMSIgTWF4PSIxIiAgICBNaW49IjAiICAgICBEaWdpdD0iNiIgRGVzYz0ic3RvcmFnZSByYXRpbyIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iUk1fQ29tS3IiICAgICAgQWxpYXM9Ik1vYmlsaXR5IFJhdGlvIiBVbml0PSIiIERlZmF1bHQ9IjEiIE1heD0iMTAwMCIgTWluPSIwLjAwMSIgRGlnaXQ9IjYiIERlc2M9Im1vYmlsaXR5IHJhdGlvIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJSTV9OZXRUb0dyb3NzIiBBbGlhcz0iTmV0LXRvLUdyb3NzIiBVbml0PSIiIERlZmF1bHQ9IjEiIE1heD0iMSIgICAgTWluPSIwIiAgICAgRGlnaXQ9IjYiIERlc2M9Im5ldC10by1ncm9zcyIgLz4NCiAgPC9QYXJhR3JvdXA+DQoNCiAgPCEtLSBSZXN1bHQgcGFyYW1ldGVycyBhcmUgc2VsZWN0ZWQgb25seSBieSByZWJ1aWxkUmVzdWx0UGFyYXMoKS4gLS0+DQogIDxQYXJhR3JvdXAgTmFtZT0iIiBBbGlhcz0iUmVzdWx0IFBhcmFtZXRlcnMiPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJSZXN1bHRfV19SdyIgICBBbGlhcz0iV2VsbCBSYWRpdXMiICAgICAgICAgICAgIFVuaXQ9Im0iICAgICAgRGVmYXVsdD0iMC4xIiAgICBNYXg9IjEwIiAgICBNaW49IjAuMDAxIiAgRGlnaXQ9IjYiICBEZXNjPSJyZXN1bHQgd2VsbGJvcmUgcmFkaXVzIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJSZXN1bHRfV19EZmMiICBBbGlhcz0iRnJhY3R1cmUgQ29uZHVjdGl2aXR5IiAgVW5pdD0ibUQubSIgICBEZWZhdWx0PSIxMDAwIiAgIE1heD0iMWUrMzAiIE1pbj0iMCIgICAgICBEaWdpdD0iNiIgIERlc2M9InJlc3VsdCBmcmFjdHVyZSBjb25kdWN0aXZpdHkiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IlJlc3VsdF9XX1NraW4iIEFsaWFzPSJTa2luIEZhY3RvciIgICAgICAgICAgICBVbml0PSIiICAgICAgIERlZmF1bHQ9IjAiICAgICAgTWF4PSIxMDAwIiAgTWluPSItMTAwIiAgIERpZ2l0PSI2IiAgRGVzYz0icmVzdWx0IHNraW4gZmFjdG9yIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJSZXN1bHRfV19DIiAgICBBbGlhcz0iV2VsbGJvcmUgU3RvcmFnZSBDb2VmZiIgVW5pdD0ibV4zL01QYSIgRGVmYXVsdD0iMCIgICAgICBNYXg9IjEwMDAiICBNaW49IjAiICAgICAgRGlnaXQ9IjYiICBEZXNjPSJyZXN1bHQgd2VsbGJvcmUgc3RvcmFnZSBjb2VmZmljaWVudCIgLz4NCg0KICAgIDxQYXJhSXRlbSBOYW1lPSJSZXN1bHRfUGkiICBBbGlhcz0iSW5pdGlhbCBGb3JtYXRpb24gUHJlc3N1cmUiIFVuaXQ9Ik1QYSIgICBEZWZhdWx0PSI0MCIgICAgIE1heD0iNTAwIiAgIE1pbj0iMC4xIiAgIERpZ2l0PSI2IiAgRGVzYz0icmVzdWx0IGluaXRpYWwgZm9ybWF0aW9uIHByZXNzdXJlIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJSZXN1bHRfSyIgICBBbGlhcz0iUGVybWVhYmlsaXR5IiAgICAgICAgICAgICAgIFVuaXQ9Im1EIiAgICBEZWZhdWx0PSIyNSIgICAgIE1heD0iMTAwMDAiIE1pbj0iMCIgICAgIERpZ2l0PSI2IiAgRGVzYz0icmVzdWx0IHBlcm1lYWJpbGl0eSIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iUmVzdWx0X2giICAgQWxpYXM9IlJlc2Vydm9pciBUaGlja25lc3MiICAgICAgICBVbml0PSJtIiAgICAgRGVmYXVsdD0iMTAiICAgICBNYXg9IjEwMDAwIiBNaW49IjFlLTA1IiBEaWdpdD0iNiIgIERlc2M9InJlc3VsdCByZXNlcnZvaXIgdGhpY2tuZXNzIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJSZXN1bHRfcGhpIiBBbGlhcz0iUG9yb3NpdHkiICAgICAgICAgICAgICAgICAgIFVuaXQ9IiIgICAgICBEZWZhdWx0PSIwLjEiICAgIE1heD0iMSIgICAgIE1pbj0iMWUtMDUiIERpZ2l0PSI2IiAgRGVzYz0icmVzdWx0IHBvcm9zaXR5IiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJSZXN1bHRfQ3RpIiBBbGlhcz0iVG90YWwgQ29tcHJlc3NpYmlsaXR5IiAgICAgIFVuaXQ9IjEvTVBhIiBEZWZhdWx0PSIwLjAwMSIgIE1heD0iMTAiICAgIE1pbj0iMWUtMzAiIERpZ2l0PSIxMCIgU2NpZW50aWZpYz0iMSIgRGVzYz0icmVzdWx0IHRvdGFsIGNvbXByZXNzaWJpbGl0eSIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iUmVzdWx0X0NmIiAgQWxpYXM9IlJvY2sgQ29tcHJlc3NpYmlsaXR5IiAgICAgICBVbml0PSIxL01QYSIgRGVmYXVsdD0iMC4wMDAxIiBNYXg9IjEwIiAgICBNaW49IjFlLTMwIiBEaWdpdD0iMTAiIFNjaWVudGlmaWM9IjEiIERlc2M9InJlc3VsdCByb2NrIGNvbXByZXNzaWJpbGl0eSIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iUmVzdWx0X1NvaSIgQWxpYXM9IkluaXRpYWwgT2lsIFNhdHVyYXRpb24iICAgICBVbml0PSIiICAgICAgRGVmYXVsdD0iMC44IiAgICBNYXg9IjEiICAgICBNaW49IjAiICAgICBEaWdpdD0iNiIgIERlc2M9InJlc3VsdCBpbml0aWFsIG9pbCBzYXR1cmF0aW9uIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJSZXN1bHRfU2dpIiBBbGlhcz0iSW5pdGlhbCBHYXMgU2F0dXJhdGlvbiIgICAgIFVuaXQ9IiIgICAgICBEZWZhdWx0PSIwIiAgICAgIE1heD0iMSIgICAgIE1pbj0iMCIgICAgIERpZ2l0PSI2IiAgRGVzYz0icmVzdWx0IGluaXRpYWwgZ2FzIHNhdHVyYXRpb24iIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IlJlc3VsdF9Td2kiIEFsaWFzPSJJbml0aWFsIFdhdGVyIFNhdHVyYXRpb24iICAgVW5pdD0iIiAgICAgIERlZmF1bHQ9IjAuMiIgICAgTWF4PSIxIiAgICAgTWluPSIwIiAgICAgRGlnaXQ9IjYiICBEZXNjPSJyZXN1bHQgaW5pdGlhbCB3YXRlciBzYXR1cmF0aW9uIiAvPg0KDQogICAgPFBhcmFJdGVtIE5hbWU9IlJlc3VsdF9CbyIgICBBbGlhcz0iT2lsIEZvcm1hdGlvbiBWb2x1bWUgRmFjdG9yIiAgIFVuaXQ9IiIgICAgICBEZWZhdWx0PSIxIiBNYXg9IjFlKzMwIiBNaW49IjAiICAgICBEaWdpdD0iNiIgIERlc2M9InJlc3VsdCBvaWwgZm9ybWF0aW9uIHZvbHVtZSBmYWN0b3IiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IlJlc3VsdF9NaXVvIiBBbGlhcz0iT2lsIFZpc2Nvc2l0eSIgICAgICAgICAgICAgICAgIFVuaXQ9Im1QYS5zIiBEZWZhdWx0PSIxIiBNYXg9IjFlKzMwIiBNaW49IjFlLTMwIiBEaWdpdD0iNiIgIERlc2M9InJlc3VsdCBvaWwgdmlzY29zaXR5IiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJSZXN1bHRfQ28iICAgQWxpYXM9Ik9pbCBDb21wcmVzc2liaWxpdHkiICAgICAgICAgICBVbml0PSIxL01QYSIgRGVmYXVsdD0iMCIgTWF4PSIxZSszMCIgTWluPSIwIiAgICBEaWdpdD0iMTAiIFNjaWVudGlmaWM9IjEiIERlc2M9InJlc3VsdCBvaWwgY29tcHJlc3NpYmlsaXR5IiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJSZXN1bHRfQnciICAgQWxpYXM9IldhdGVyIEZvcm1hdGlvbiBWb2x1bWUgRmFjdG9yIiBVbml0PSJtMy9tMyIgRGVmYXVsdD0iMSIgTWF4PSIxZSszMCIgTWluPSIwIiAgICAgRGlnaXQ9IjYiICBEZXNjPSJyZXN1bHQgd2F0ZXIgZm9ybWF0aW9uIHZvbHVtZSBmYWN0b3IiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IlJlc3VsdF9NaXV3IiBBbGlhcz0iV2F0ZXIgVmlzY29zaXR5IiAgICAgICAgICAgICAgIFVuaXQ9Im1QYS5zIiBEZWZhdWx0PSIxIiBNYXg9IjFlKzMwIiBNaW49IjFlLTMwIiBEaWdpdD0iNiIgIERlc2M9InJlc3VsdCB3YXRlciB2aXNjb3NpdHkiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IlJlc3VsdF9DdyIgICBBbGlhcz0iV2F0ZXIgQ29tcHJlc3NpYmlsaXR5IiAgICAgICAgIFVuaXQ9IjEvTVBhIiBEZWZhdWx0PSIwIiBNYXg9IjFlKzMwIiBNaW49IjAiICAgIERpZ2l0PSIxMCIgU2NpZW50aWZpYz0iMSIgRGVzYz0icmVzdWx0IHdhdGVyIGNvbXByZXNzaWJpbGl0eSIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iUmVzdWx0X0JnIiAgIEFsaWFzPSJHYXMgRm9ybWF0aW9uIFZvbHVtZSBGYWN0b3IiICAgVW5pdD0ibTMvbTMiIERlZmF1bHQ9IjEiIE1heD0iMWUrMzAiIE1pbj0iMCIgICAgIERpZ2l0PSI2IiAgRGVzYz0icmVzdWx0IGdhcyBmb3JtYXRpb24gdm9sdW1lIGZhY3RvciIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iUmVzdWx0X01pdWciIEFsaWFzPSJHYXMgVmlzY29zaXR5IiAgICAgICAgICAgICAgICAgVW5pdD0ibVBhLnMiIERlZmF1bHQ9IjEiIE1heD0iMWUrMzAiIE1pbj0iMWUtMzAiIERpZ2l0PSI2IiAgRGVzYz0icmVzdWx0IGdhcyB2aXNjb3NpdHkiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IlJlc3VsdF9DZyIgICBBbGlhcz0iR2FzIENvbXByZXNzaWJpbGl0eSIgICAgICAgICAgIFVuaXQ9IjEvTVBhIiBEZWZhdWx0PSIwIiBNYXg9IjFlKzMwIiBNaW49IjAiICAgIERpZ2l0PSIxMCIgU2NpZW50aWZpYz0iMSIgRGVzYz0icmVzdWx0IGdhcyBjb21wcmVzc2liaWxpdHkiIC8+DQogIDwvUGFyYUdyb3VwPg0KDQo8L1Jvb3Q+DQo= \ No newline at end of file +PD94bWwgdmVycup_mpac2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4NCg0KPCEtLSoqKioqKioqKioqKiwzyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiotLT4NCjwhLS0gICAgVGhpcyBmaWxlIGRlZmluZXMgcGFyYW1ldGVycyBmb3IgdGhlIFdUQUkgTnVtZXJpY2FsIChOTSkgICAgLS0+DQo8IS0tICAgIG1vZHVsZS4gT25seSByZXNlcnZvaXIsIHdlbGwsIGFuZCBnZW9tZXRyeSBwYXJhbWV0ZXJzICAgICAgICAtLT4NCjwhLS0gICAgcmVxdWlyZWQgYnkgdGhlIFBFQkkgc29sdmVyIGFyZSBpbmNsdWRlZC4gICAgICAgICAgICAgICAgICAgIC0tPg0KPCEtLSAgICBEYXRlOiAyMDI2MDYxNSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLS0+DQo8IS0tKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi0tPg0KDQo8IS0tDQogICAgUGFyYW1ldGVyIHNjb3BlOiByZXNlcnZvaXIsIHdlbGwsIGFuZCBnZW9tZXRyeSBwYXJhbWV0ZXJzIHJlcXVpcmVkIGJ5IHRoZSBQRUJJIHNvbHZlcg0KICAgIENvcnJlc3BvbmRzIHRvIEhYX05XVE1fTU9ERUxfSU5QVVQgc3RydWN0IGZpZWxkcw0KICAgIExvYWRlZCB2aWEgX3BhcmFIZWxwZXItPmxvYWRQYXJhRGVmaW5lcygpLCBzS2V5ID0gc19ObV9TZXJpZQ0KLS0+DQoNCjxSb290Pg0KDQogIDxQYXJhR3JvdXAgTmFtZT0iIiBBbGlhcz0iVGltZSBTdGVwIFNldHRpbmdzIj4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iTk1fVGltZUdyb3d0aEV4cG9uZW50IiBBbGlhcz0iVGltZSBHcm93dGggRXhwb25lbnQiIFVuaXQ9IiIgIERlZmF1bHQ9IjEuMDUiICAgTWF4PSIxMCIgICAgTWluPSIxIiAgICAgRGlnaXQ9IjYiIERlc2M9InRpbWUgZ3Jvd3RoIGV4cG9uZW50IiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJOTV9EdE1pbiIgICAgICAgICAgICAgIEFsaWFzPSJNaW5pbXVtIFRpbWUgU3RlcCIgICAgVW5pdD0iaHIiIERlZmF1bHQ9IjAuMDAyNSIgTWF4PSIxZSszMCIgTWluPSIxZS0xMiIgRGlnaXQ9IjYiIERlc2M9Im1pbmltdW0gdGltZSBzdGVwIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJOTV9EdE1heCIgICAgICAgICAgICAgIEFsaWFzPSJNYXhpbXVtIFRpbWUgU3RlcCIgICAgVW5pdD0iaHIiIERlZmF1bHQ9IjEyLjUiICAgTWF4PSIxZSszMCIgTWluPSIxZS0xMiIgRGlnaXQ9IjYiIERlc2M9Im1heGltdW0gdGltZSBzdGVwIiAvPg0KICA8L1BhcmFHcm91cD4NCg0KICA8UGFyYUdyb3VwIE5hbWU9IiIgQWxpYXM9IlJlc2Vydm9pciBQYXJhbWV0ZXJzIj4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iaCIgICBBbGlhcz0iUmVzZXJ2b2lyIFRoaWNrbmVzcyIgICAgICAgICBVbml0PSJtIiAgICAgRGVmYXVsdD0iMTAiICAgIE1heD0iMTAwMDAiICBNaW49IjFlLTA1IiAgRGlnaXQ9IjMiICBEZXNjPSJyZXNlcnZvaXIgdGhpY2tuZXNzIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJQaSIgIEFsaWFzPSJJbml0aWFsIFByZXNzdXJlIiAgICAgICAgICAgIFVuaXQ9Ik1QYSIgICBEZWZhdWx0PSI0MCIgICAgTWF4PSI1MDAiICAgIE1pbj0iMC4xIiAgICBEaWdpdD0iNSIgIERlc2M9ImluaXRpYWwgZm9ybWF0aW9uIHByZXNzdXJlIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJLIiAgIEFsaWFzPSJQZXJtZWFiaWxpdHkiICAgICAgICAgICAgICAgIFVuaXQ9Im1EIiAgICBEZWZhdWx0PSIyNSIgICAgTWF4PSIxMDAwMCIgIE1pbj0iMCIgICAgICBEaWdpdD0iNiIgIERlc2M9InBlcm1lYWJpbGl0eSIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0icGhpIiBBbGlhcz0iUG9yb3NpdHkiICAgICAgICAgICAgICAgICAgICBVbml0PSIiICAgICAgRGVmYXVsdD0iMC4xIiAgIE1heD0iMSIgICAgICBNaW49IjFlLTA1IiAgRGlnaXQ9IjQiICBEZXNjPSJwb3Jvc2l0eSIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iQm8iICBBbGlhcz0iT2lsIEZvcm1hdGlvbiBWb2x1bWUgRmFjdG9yIiBVbml0PSIiICAgICAgRGVmYXVsdD0iMS4yIiAgIE1heD0iMTAiICAgICBNaW49IjFlLTA2IiAgRGlnaXQ9IjYiICBEZXNjPSJvaWwgZm9ybWF0aW9uIHZvbHVtZSBmYWN0b3IiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9Ik1pdW8iIEFsaWFzPSJPaWwgVmlzY29zaXR5IiAgICAgICAgICAgICAgVW5pdD0ibVBhLnMiIERlZmF1bHQ9IjAuNSIgICBNYXg9IjEwMDAwIiAgTWluPSIxZS0wNiIgIERpZ2l0PSI2IiAgRGVzYz0ib2lsIHZpc2Nvc2l0eSIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iQnciICBBbGlhcz0iV2F0ZXIgRm9ybWF0aW9uIFZvbHVtZSBGYWN0b3IiIFVuaXQ9IiIgICAgRGVmYXVsdD0iMSIgICAgIE1heD0iMTAiICAgICBNaW49IjFlLTA2IiAgRGlnaXQ9IjYiICBEZXNjPSJ3YXRlciBmb3JtYXRpb24gdm9sdW1lIGZhY3RvciIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iTWl1dyIgQWxpYXM9IldhdGVyIFZpc2Nvc2l0eSIgICAgICAgICAgICBVbml0PSJtUGEucyIgRGVmYXVsdD0iMSIgICAgIE1heD0iMTAwMDAiICBNaW49IjFlLTA2IiAgRGlnaXQ9IjYiICBEZXNjPSJ3YXRlciB2aXNjb3NpdHkiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IkN0aSIgQWxpYXM9IlRvdGFsIENvbXByZXNzaWJpbGl0eSIgICAgICAgVW5pdD0iMS9NUGEiIERlZmF1bHQ9IjAuMDAxIiBNYXg9IjEwIiAgICAgTWluPSIxZS0zMCIgIERpZ2l0PSIxMCIgU2NpZW50aWZpYz0iMSIgRGVzYz0idG90YWwgY29tcHJlc3NpYmlsaXR5IiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJDZiIgIEFsaWFzPSJSb2NrIENvbXByZXNzaWJpbGl0eSIgICAgICAgIFVuaXQ9IjEvTVBhIiBEZWZhdWx0PSIwLjAwMDEiIE1heD0iMTAiICAgIE1pbj0iMWUtMzAiICBEaWdpdD0iMTAiIFNjaWVudGlmaWM9IjEiIERlc2M9InJvY2sgY29tcHJlc3NpYmlsaXR5IiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJTb2kiIEFsaWFzPSJJbml0aWFsIE9pbCBTYXR1cmF0aW9uIiAgICAgIFVuaXQ9IiIgICAgICBEZWZhdWx0PSIwLjgiICAgTWF4PSIxIiAgICAgIE1pbj0iMCIgICAgICBEaWdpdD0iNiIgIERlc2M9ImluaXRpYWwgb2lsIHNhdHVyYXRpb24iIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IlNnaSIgQWxpYXM9IkluaXRpYWwgR2FzIFNhdHVyYXRpb24iICAgICAgVW5pdD0iIiAgICAgIERlZmF1bHQ9IjAiICAgICBNYXg9IjEiICAgICAgTWluPSIwIiAgICAgIERpZ2l0PSI2IiAgRGVzYz0iaW5pdGlhbCBnYXMgc2F0dXJhdGlvbiIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iU3dpIiBBbGlhcz0iSW5pdGlhbCBXYXRlciBTYXR1cmF0aW9uIiAgICBVbml0PSIiICAgICAgRGVmYXVsdD0iMC4yIiAgIE1heD0iMSIgICAgICBNaW49IjAiICAgICAgRGlnaXQ9IjYiICBEZXNjPSJpbml0aWFsIHdhdGVyIHNhdHVyYXRpb24iIC8+DQogIDwvUGFyYUdyb3VwPg0KDQogIDxQYXJhR3JvdXAgTmFtZT0iIiBBbGlhcz0iV2VsbCBQYXJhbWV0ZXJzIj4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iV19YIiAgICBBbGlhcz0iWCBDb29yZGluYXRlIiAgICAgICAgICAgIFVuaXQ9Im0iICAgICAgRGVmYXVsdD0iMCIgICAgIE1heD0iMTAwMDAiICBNaW49Ii0xMDAwMCIgRGlnaXQ9IjYiICBEZXNjPSJ3ZWxsIFggY29vcmRpbmF0ZSIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iV19ZIiAgICBBbGlhcz0iWSBDb29yZGluYXRlIiAgICAgICAgICAgIFVuaXQ9Im0iICAgICAgRGVmYXVsdD0iMCIgICAgIE1heD0iMTAwMDAiICBNaW49Ii0xMDAwMCIgRGlnaXQ9IjYiICBEZXNjPSJ3ZWxsIFkgY29vcmRpbmF0ZSIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iV19SdyIgICBBbGlhcz0iV2VsbGJvcmUgUmFkaXVzIiAgICAgICAgIFVuaXQ9Im0iICAgICAgRGVmYXVsdD0iMC4xIiAgIE1heD0iMTAiICAgICBNaW49IjAuMDAxIiAgRGlnaXQ9IjYiICBEZXNjPSJ3ZWxsYm9yZSByYWRpdXMiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IldfU2tpbiIgQWxpYXM9IlNraW4gRmFjdG9yIiAgICAgICAgICAgICBVbml0PSIiICAgICAgIERlZmF1bHQ9IjAiICAgICBNYXg9IjEwMDAiICAgTWluPSItMTAwIiAgIERpZ2l0PSI2IiAgRGVzYz0ic2tpbiBmYWN0b3IiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IldfQyIgICAgQWxpYXM9IldlbGxib3JlIFN0b3JhZ2UgQ29lZmYiICBVbml0PSJtXjMvTVBhIiBEZWZhdWx0PSIwIiAgICAgTWF4PSIxMDAwIiAgIE1pbj0iMCIgICAgICBEaWdpdD0iNiIgIERlc2M9IndlbGxib3JlIHN0b3JhZ2UgY29lZmZpY2llbnQiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IldfQm90dG9taG9sZU1EIiAgICAgICBBbGlhcz0iQm90dG9taG9sZSBNRCIgICAgICAgICAgVW5pdD0ibSIgICAgRGVmYXVsdD0iNjAwMCIgTWF4PSIxMDAwMDAiIE1pbj0iMCIgICAgIERpZ2l0PSI2IiBEZXNjPSJib3R0b21ob2xlIG1lYXN1cmVkIGRlcHRoIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJXX1dlbGxMZW5ndGgiICAgICAgICAgQWxpYXM9IldlbGwgTGVuZ3RoIiAgICAgICAgICAgIFVuaXQ9Im0iICAgIERlZmF1bHQ9IjIwMCIgIE1heD0iMTAwMDAiICBNaW49IjFlLTA1IiBEaWdpdD0iNiIgRGVzYz0id2VsbGJvcmUgbGVuZ3RoIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJXX1BlcmZvcmF0aW9uTWRTdGFydCIgQWxpYXM9IlBlcmZvcmF0aW9uIFN0YXJ0IE1EIiAgIFVuaXQ9Im0iICAgIERlZmF1bHQ9IjYwMDAiIE1heD0iMTAwMDAwIiBNaW49IjAiICAgICBEaWdpdD0iNiIgRGVzYz0icGVyZm9yYXRpb24gc3RhcnQgbWVhc3VyZWQgZGVwdGgiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IldfUGVyZm9yYXRpb25NZEVuZCIgICBBbGlhcz0iUGVyZm9yYXRpb24gRW5kIE1EIiAgICAgVW5pdD0ibSIgICAgRGVmYXVsdD0iNjAzMCIgTWF4PSIxMDAwMDAiIE1pbj0iMCIgICAgIERpZ2l0PSI2IiBEZXNjPSJwZXJmb3JhdGlvbiBlbmQgbWVhc3VyZWQgZGVwdGgiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IldfRHJhaW5BbmdsZSIgICAgICAgICBBbGlhcz0iRHJhaW4gQW5nbGUiICAgICAgICAgICAgVW5pdD0iZGVnIiAgRGVmYXVsdD0iMCIgICAgTWF4PSIzNjAiICAgTWluPSItMzYwIiAgRGlnaXQ9IjYiIERlc2M9Imhvcml6b250YWwgd2VsbCBkcmFpbiBhbmdsZSIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iV19OdW1iZXJPZkZyYWN0dXJlcyIgIEFsaWFzPSJOdW1iZXIgb2YgRnJhY3R1cmVzIiAgICBVbml0PSIiICAgICBEZWZhdWx0PSIxNSIgICBNYXg9IjEwMDAiICBNaW49IjIiICAgICBEaWdpdD0iMCIgRGVzYz0ibnVtYmVyIG9mIGZyYWN0dXJlcyIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iV19GcmFjdHVyZUhhbGZMZW5ndGgiIEFsaWFzPSJGcmFjdHVyZSBIYWxmLUxlbmd0aCIgICBVbml0PSJtIiAgICBEZWZhdWx0PSI1MCIgICBNYXg9IjEwMDAwIiBNaW49IjFlLTA1IiBEaWdpdD0iNiIgRGVzYz0iZnJhY3R1cmUgaGFsZi1sZW5ndGgiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IldfRnJhY3R1cmVBbmdsZSIgICAgICBBbGlhcz0iRnJhY3R1cmUgQW5nbGUiICAgICAgICAgVW5pdD0iZGVnIiAgRGVmYXVsdD0iOTAiICAgTWF4PSIzNjAiICAgTWluPSItMzYwIiAgRGlnaXQ9IjYiIERlc2M9ImZyYWN0dXJlIGFuZ2xlIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJXX0ZyYWN0dXJlSGVpZ2h0IiAgICAgQWxpYXM9IkZyYWN0dXJlIEhlaWdodCIgICAgICAgIFVuaXQ9Im0iICAgIERlZmF1bHQ9IjEwIiAgIE1heD0iMTAwMDAiIE1pbj0iMWUtMDUiIERpZ2l0PSI2IiBEZXNjPSJmcmFjdHVyZSBoZWlnaHQiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IldfRnJhY3R1cmVNaWRQb2ludEhlaWdodCIgQWxpYXM9IkZyYWN0dXJlIE1pZHBvaW50IEhlaWdodCIgVW5pdD0ibSIgRGVmYXVsdD0iNSIgTWF4PSIxMDAwMCIgTWluPSIwIiBEaWdpdD0iNiIgRGVzYz0iZnJhY3R1cmUgbWlkcG9pbnQgaGVpZ2h0IiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJXX0ZyYWN0dXJlV2lkdGgiICAgICAgQWxpYXM9IkZyYWN0dXJlIFdpZHRoIiAgICAgICAgIFVuaXQ9Im0iICAgIERlZmF1bHQ9IjAuMDAxIiBNYXg9IjEwMCIgIE1pbj0iMWUtMDgiIERpZ2l0PSI4IiBEZXNjPSJmcmFjdHVyZSB3aWR0aCIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iV19EZmMiICAgICAgICAgICAgICAgIEFsaWFzPSJGcmFjdHVyZSBDb25kdWN0aXZpdHkiICBVbml0PSJtRC5tIiBEZWZhdWx0PSIxMDAwIiBNYXg9IjFlKzMwIiBNaW49IjAiICAgICBEaWdpdD0iNiIgRGVzYz0iZnJhY3R1cmUgY29uZHVjdGl2aXR5IiAvPg0KICA8L1BhcmFHcm91cD4NCg0KICA8UGFyYUdyb3VwIE5hbWU9IiIgQWxpYXM9IkluZGVwZW5kZW50IEZyYWN0dXJlIFBhcmFtZXRlcnMiPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJGX1gwIiBBbGlhcz0iU3RhcnQgWDAiICAgICAgICAgICAgICBVbml0PSJtIiAgICBEZWZhdWx0PSIwIiBNYXg9IjEwMDAwIiBNaW49Ii0xMDAwMCIgRGlnaXQ9IjYiIERlc2M9ImZyYWN0dXJlIHN0YXJ0IFggY29vcmRpbmF0ZSIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iRl9ZMCIgQWxpYXM9IlN0YXJ0IFkwIiAgICAgICAgICAgICAgVW5pdD0ibSIgICAgRGVmYXVsdD0iMCIgTWF4PSIxMDAwMCIgTWluPSItMTAwMDAiIERpZ2l0PSI2IiBEZXNjPSJmcmFjdHVyZSBzdGFydCBZIGNvb3JkaW5hdGUiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IkZfWDEiIEFsaWFzPSJFbmQgWDEiICAgICAgICAgICAgICAgIFVuaXQ9Im0iICAgIERlZmF1bHQ9IjAiIE1heD0iMTAwMDAiIE1pbj0iLTEwMDAwIiBEaWdpdD0iNiIgRGVzYz0iZnJhY3R1cmUgZW5kIFggY29vcmRpbmF0ZSIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iRl9ZMSIgQWxpYXM9IkVuZCBZMSIgICAgICAgICAgICAgICAgVW5pdD0ibSIgICAgRGVmYXVsdD0iMCIgTWF4PSIxMDAwMCIgTWluPSItMTAwMDAiIERpZ2l0PSI2IiBEZXNjPSJmcmFjdHVyZSBlbmQgWSBjb29yZGluYXRlIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJGX0ZDIiBBbGlhcz0iRnJhY3R1cmUgQ29uZHVjdGl2aXR5IiBVbml0PSJtRC5tIiBEZWZhdWx0PSIxIiBNYXg9IjFlKzMwIiBNaW49IjAiICAgICAgRGlnaXQ9IjYiIERlc2M9ImZyYWN0dXJlIGNvbmR1Y3Rpdml0eSIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iRl9EVyIgQWxpYXM9IkZyYWN0dXJlIFdpZHRoIFBhcmFtZXRlciIgVW5pdD0iIiBEZWZhdWx0PSIxIiBNYXg9IjFlKzMwIiBNaW49IjAiIERpZ2l0PSI2IiBEZXNjPSJmcmFjdHVyZSB3aWR0aCBwYXJhbWV0ZXIiIC8+DQogIDwvUGFyYUdyb3VwPg0KDQogIDxQYXJhR3JvdXAgTmFtZT0iIiBBbGlhcz0iRmF1bHQgUGFyYW1ldGVycyI+DQogICAgPFBhcmFJdGVtIE5hbWU9IkZUX1gwIiBBbGlhcz0iU3RhcnQgWDAiIFVuaXQ9Im0iIERlZmF1bHQ9IjAiIE1heD0iMTAwMDAiIE1pbj0iLTEwMDAwIiBEaWdpdD0iNiIgRGVzYz0iZmF1bHQgc3RhcnQgWCBjb29yZGluYXRlIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJGVF9ZMCIgQWxpYXM9IlN0YXJ0IFkwIiBVbml0PSJtIiBEZWZhdWx0PSIwIiBNYXg9IjEwMDAwIiBNaW49Ii0xMDAwMCIgRGlnaXQ9IjYiIERlc2M9ImZhdWx0IHN0YXJ0IFkgY29vcmRpbmF0ZSIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iRlRfWDEiIEFsaWFzPSJFbmQgWDEiIFVuaXQ9Im0iIERlZmF1bHQ9IjAiIE1heD0iMTAwMDAiIE1pbj0iLTEwMDAwIiBEaWdpdD0iNiIgRGVzYz0iZmF1bHQgZW5kIFggY29vcmRpbmF0ZSIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iRlRfWTEiIEFsaWFzPSJFbmQgWTEiIFVuaXQ9Im0iIERlZmF1bHQ9IjAiIE1heD0iMTAwMDAiIE1pbj0iLTEwMDAwIiBEaWdpdD0iNiIgRGVzYz0iZmF1bHQgZW5kIFkgY29vcmRpbmF0ZSIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iRlRfTGVha2FnZSIgQWxpYXM9IkxlYWthZ2UgQ29lZmZpY2llbnQiIFVuaXQ9IiIgRGVmYXVsdD0iMSIgTWF4PSIxZSszMCIgTWluPSIwIiBEaWdpdD0iNiIgRGVzYz0iZmF1bHQgbGVha2FnZSBjb2VmZmljaWVudCIgLz4NCiAgPC9QYXJhR3JvdXA+DQoNCiAgPFBhcmFHcm91cCBOYW1lPSIiIEFsaWFzPSJSZWN0YW5nbGUgQm91bmRhcnkgUGFyYW1ldGVycyI+DQogICAgPFBhcmFJdGVtIE5hbWU9IkJSX1hNaW4iIEFsaWFzPSJMZWZ0IEJvdW5kYXJ5IFgiIFVuaXQ9Im0iIERlZmF1bHQ9IjAiIE1heD0iMTAwMDAiIE1pbj0iLTEwMDAwIiBEaWdpdD0iNiIgRGVzYz0icmVjdGFuZ2xlIGJvdW5kYXJ5IG1pbmltdW0gWCIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iQlJfWU1pbiIgQWxpYXM9IkJvdHRvbSBCb3VuZGFyeSBZIiBVbml0PSJtIiBEZWZhdWx0PSIwIiBNYXg9IjEwMDAwIiBNaW49Ii0xMDAwMCIgRGlnaXQ9IjYiIERlc2M9InJlY3RhbmdsZSBib3VuZGFyeSBtaW5pbXVtIFkiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IkJSX1hNYXgiIEFsaWFzPSJSaWdodCBCb3VuZGFyeSBYIiBVbml0PSJtIiBEZWZhdWx0PSIwIiBNYXg9IjEwMDAwIiBNaW49Ii0xMDAwMCIgRGlnaXQ9IjYiIERlc2M9InJlY3RhbmdsZSBib3VuZGFyeSBtYXhpbXVtIFgiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IkJSX1lNYXgiIEFsaWFzPSJUb3AgQm91bmRhcnkgWSIgVW5pdD0ibSIgRGVmYXVsdD0iMCIgTWF4PSIxMDAwMCIgTWluPSItMTAwMDAiIERpZ2l0PSI2IiBEZXNjPSJyZWN0YW5nbGUgYm91bmRhcnkgbWF4aW11bSBZIiAvPg0KICA8L1BhcmFHcm91cD4NCg0KICA8UGFyYUdyb3VwIE5hbWU9IiIgQWxpYXM9IkNpcmNsZSBCb3VuZGFyeSBQYXJhbWV0ZXJzIj4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iQkNfQ2VudGVyWCIgQWxpYXM9IkNlbnRlciBYIiBVbml0PSJtIiBEZWZhdWx0PSIwIiBNYXg9IjEwMDAwIiBNaW49Ii0xMDAwMCIgRGlnaXQ9IjYiIERlc2M9ImNpcmNsZSBib3VuZGFyeSBjZW50ZXIgWCIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iQkNfQ2VudGVyWSIgQWxpYXM9IkNlbnRlciBZIiBVbml0PSJtIiBEZWZhdWx0PSIwIiBNYXg9IjEwMDAwIiBNaW49Ii0xMDAwMCIgRGlnaXQ9IjYiIERlc2M9ImNpcmNsZSBib3VuZGFyeSBjZW50ZXIgWSIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iQkNfUmFkaXVzIiAgQWxpYXM9IlJhZGl1cyIgICBVbml0PSJtIiBEZWZhdWx0PSIxIiBNYXg9IjEwMDAwIiBNaW49IjFlLTA1IiAgRGlnaXQ9IjYiIERlc2M9ImNpcmNsZSBib3VuZGFyeSByYWRpdXMiIC8+DQogIDwvUGFyYUdyb3VwPg0KDQogIDxQYXJhR3JvdXAgTmFtZT0iIiBBbGlhcz0iUG9seWdvbiBCb3VuZGFyeSBWZXJ0ZXggUGFyYW1ldGVycyI+DQogICAgPFBhcmFJdGVtIE5hbWU9IkJQX1giIEFsaWFzPSJYIENvb3JkaW5hdGUiIFVuaXQ9Im0iIERlZmF1bHQ9IjAiIE1heD0iMTAwMDAiIE1pbj0iLTEwMDAwIiBEaWdpdD0iNiIgRGVzYz0icG9seWdvbiBib3VuZGFyeSB2ZXJ0ZXggWCIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iQlBfWSIgQWxpYXM9IlkgQ29vcmRpbmF0ZSIgVW5pdD0ibSIgRGVmYXVsdD0iMCIgTWF4PSIxMDAwMCIgTWluPSItMTAwMDAiIERpZ2l0PSI2IiBEZXNjPSJwb2x5Z29uIGJvdW5kYXJ5IHZlcnRleCBZIiAvPg0KICA8L1BhcmFHcm91cD4NCg0KICA8UGFyYUdyb3VwIE5hbWU9IiIgQWxpYXM9IlJlZ2lvbiBQYXJhbWV0ZXJzIj4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iUl9MZWFrYWdlIiBBbGlhcz0iTGVha2FnZSBDb2VmZmljaWVudCIgVW5pdD0iIiBEZWZhdWx0PSIxIiBNYXg9IjFlKzMwIiBNaW49IjAiIERpZ2l0PSI2IiBEZXNjPSJyZWdpb24gbGVha2FnZSBjb2VmZmljaWVudCIgLz4NCiAgPC9QYXJhR3JvdXA+DQoNCiAgPFBhcmFHcm91cCBOYW1lPSIiIEFsaWFzPSJSZWdpb24gTWFyayBQYXJhbWV0ZXJzIj4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iUk1fQ29tVyIgICAgICAgQWxpYXM9IlN0b3JhZ2UgUmF0aW8iIFVuaXQ9IiIgRGVmYXVsdD0iMSIgTWF4PSIxIiAgICBNaW49IjAiICAgICBEaWdpdD0iNiIgRGVzYz0ic3RvcmFnZSByYXRpbyIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iUk1fQ29tS3IiICAgICAgQWxpYXM9Ik1vYmlsaXR5IFJhdGlvIiBVbml0PSIiIERlZmF1bHQ9IjEiIE1heD0iMTAwMCIgTWluPSIwLjAwMSIgRGlnaXQ9IjYiIERlc2M9Im1vYmlsaXR5IHJhdGlvIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJSTV9OZXRUb0dyb3NzIiBBbGlhcz0iTmV0LXRvLUdyb3NzIiBVbml0PSIiIERlZmF1bHQ9IjEiIE1heD0iMSIgICAgTWluPSIwIiAgICAgRGlnaXQ9IjYiIERlc2M9Im5ldC10by1ncm9zcyIgLz4NCiAgPC9QYXJhR3JvdXA+DQoNCiAgPCEtLSBSZXN1bHQgcGFyYW1ldGVycyBhcmUgc2VsZWN0ZWQgb25seSBieSByZWJ1aWxkUmVzdWx0UGFyYXMoKS4gLS0+DQogIDxQYXJhR3JvdXAgTmFtZT0iIiBBbGlhcz0iUmVzdWx0IFBhcmFtZXRlcnMiPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJSZXN1bHRfV19SdyIgICBBbGlhcz0iV2VsbCBSYWRpdXMiICAgICAgICAgICAgIFVuaXQ9Im0iICAgICAgRGVmYXVsdD0iMC4xIiAgICBNYXg9IjEwIiAgICBNaW49IjAuMDAxIiAgRGlnaXQ9IjYiICBEZXNjPSJyZXN1bHQgd2VsbGJvcmUgcmFkaXVzIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJSZXN1bHRfV19EZmMiICBBbGlhcz0iRnJhY3R1cmUgQ29uZHVjdGl2aXR5IiAgVW5pdD0ibUQubSIgICBEZWZhdWx0PSIxMDAwIiAgIE1heD0iMWUrMzAiIE1pbj0iMCIgICAgICBEaWdpdD0iNiIgIERlc2M9InJlc3VsdCBmcmFjdHVyZSBjb25kdWN0aXZpdHkiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IlJlc3VsdF9XX1NraW4iIEFsaWFzPSJTa2luIEZhY3RvciIgICAgICAgICAgICBVbml0PSIiICAgICAgIERlZmF1bHQ9IjAiICAgICAgTWF4PSIxMDAwIiAgTWluPSItMTAwIiAgIERpZ2l0PSI2IiAgRGVzYz0icmVzdWx0IHNraW4gZmFjdG9yIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJSZXN1bHRfV19DIiAgICBBbGlhcz0iV2VsbGJvcmUgU3RvcmFnZSBDb2VmZiIgVW5pdD0ibV4zL01QYSIgRGVmYXVsdD0iMCIgICAgICBNYXg9IjEwMDAiICBNaW49IjAiICAgICAgRGlnaXQ9IjYiICBEZXNjPSJyZXN1bHQgd2VsbGJvcmUgc3RvcmFnZSBjb2VmZmljaWVudCIgLz4NCg0KICAgIDxQYXJhSXRlbSBOYW1lPSJSZXN1bHRfUGkiICBBbGlhcz0iSW5pdGlhbCBGb3JtYXRpb24gUHJlc3N1cmUiIFVuaXQ9Ik1QYSIgICBEZWZhdWx0PSI0MCIgICAgIE1heD0iNTAwIiAgIE1pbj0iMC4xIiAgIERpZ2l0PSI2IiAgRGVzYz0icmVzdWx0IGluaXRpYWwgZm9ybWF0aW9uIHByZXNzdXJlIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJSZXN1bHRfSyIgICBBbGlhcz0iUGVybWVhYmlsaXR5IiAgICAgICAgICAgICAgIFVuaXQ9Im1EIiAgICBEZWZhdWx0PSIyNSIgICAgIE1heD0iMTAwMDAiIE1pbj0iMCIgICAgIERpZ2l0PSI2IiAgRGVzYz0icmVzdWx0IHBlcm1lYWJpbGl0eSIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iUmVzdWx0X2giICAgQWxpYXM9IlJlc2Vydm9pciBUaGlja25lc3MiICAgICAgICBVbml0PSJtIiAgICAgRGVmYXVsdD0iMTAiICAgICBNYXg9IjEwMDAwIiBNaW49IjFlLTA1IiBEaWdpdD0iNiIgIERlc2M9InJlc3VsdCByZXNlcnZvaXIgdGhpY2tuZXNzIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJSZXN1bHRfcGhpIiBBbGlhcz0iUG9yb3NpdHkiICAgICAgICAgICAgICAgICAgIFVuaXQ9IiIgICAgICBEZWZhdWx0PSIwLjEiICAgIE1heD0iMSIgICAgIE1pbj0iMWUtMDUiIERpZ2l0PSI2IiAgRGVzYz0icmVzdWx0IHBvcm9zaXR5IiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJSZXN1bHRfQ3RpIiBBbGlhcz0iVG90YWwgQ29tcHJlc3NpYmlsaXR5IiAgICAgIFVuaXQ9IjEvTVBhIiBEZWZhdWx0PSIwLjAwMSIgIE1heD0iMTAiICAgIE1pbj0iMWUtMzAiIERpZ2l0PSIxMCIgU2NpZW50aWZpYz0iMSIgRGVzYz0icmVzdWx0IHRvdGFsIGNvbXByZXNzaWJpbGl0eSIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iUmVzdWx0X0NmIiAgQWxpYXM9IlJvY2sgQ29tcHJlc3NpYmlsaXR5IiAgICAgICBVbml0PSIxL01QYSIgRGVmYXVsdD0iMC4wMDAxIiBNYXg9IjEwIiAgICBNaW49IjFlLTMwIiBEaWdpdD0iMTAiIFNjaWVudGlmaWM9IjEiIERlc2M9InJlc3VsdCByb2NrIGNvbXByZXNzaWJpbGl0eSIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iUmVzdWx0X1NvaSIgQWxpYXM9IkluaXRpYWwgT2lsIFNhdHVyYXRpb24iICAgICBVbml0PSIiICAgICAgRGVmYXVsdD0iMC44IiAgICBNYXg9IjEiICAgICBNaW49IjAiICAgICBEaWdpdD0iNiIgIERlc2M9InJlc3VsdCBpbml0aWFsIG9pbCBzYXR1cmF0aW9uIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJSZXN1bHRfU2dpIiBBbGlhcz0iSW5pdGlhbCBHYXMgU2F0dXJhdGlvbiIgICAgIFVuaXQ9IiIgICAgICBEZWZhdWx0PSIwIiAgICAgIE1heD0iMSIgICAgIE1pbj0iMCIgICAgIERpZ2l0PSI2IiAgRGVzYz0icmVzdWx0IGluaXRpYWwgZ2FzIHNhdHVyYXRpb24iIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IlJlc3VsdF9Td2kiIEFsaWFzPSJJbml0aWFsIFdhdGVyIFNhdHVyYXRpb24iICAgVW5pdD0iIiAgICAgIERlZmF1bHQ9IjAuMiIgICAgTWF4PSIxIiAgICAgTWluPSIwIiAgICAgRGlnaXQ9IjYiICBEZXNjPSJyZXN1bHQgaW5pdGlhbCB3YXRlciBzYXR1cmF0aW9uIiAvPg0KDQogICAgPFBhcmFJdGVtIE5hbWU9IlJlc3VsdF9CbyIgICBBbGlhcz0iT2lsIEZvcm1hdGlvbiBWb2x1bWUgRmFjdG9yIiAgIFVuaXQ9IiIgICAgICBEZWZhdWx0PSIxIiBNYXg9IjFlKzMwIiBNaW49IjAiICAgICBEaWdpdD0iNiIgIERlc2M9InJlc3VsdCBvaWwgZm9ybWF0aW9uIHZvbHVtZSBmYWN0b3IiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IlJlc3VsdF9NaXVvIiBBbGlhcz0iT2lsIFZpc2Nvc2l0eSIgICAgICAgICAgICAgICAgIFVuaXQ9Im1QYS5zIiBEZWZhdWx0PSIxIiBNYXg9IjFlKzMwIiBNaW49IjFlLTMwIiBEaWdpdD0iNiIgIERlc2M9InJlc3VsdCBvaWwgdmlzY29zaXR5IiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJSZXN1bHRfQ28iICAgQWxpYXM9Ik9pbCBDb21wcmVzc2liaWxpdHkiICAgICAgICAgICBVbml0PSIxL01QYSIgRGVmYXVsdD0iMCIgTWF4PSIxZSszMCIgTWluPSIwIiAgICBEaWdpdD0iMTAiIFNjaWVudGlmaWM9IjEiIERlc2M9InJlc3VsdCBvaWwgY29tcHJlc3NpYmlsaXR5IiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJSZXN1bHRfQnciICAgQWxpYXM9IldhdGVyIEZvcm1hdGlvbiBWb2x1bWUgRmFjdG9yIiBVbml0PSJtMy9tMyIgRGVmYXVsdD0iMSIgTWF4PSIxZSszMCIgTWluPSIwIiAgICAgRGlnaXQ9IjYiICBEZXNjPSJyZXN1bHQgd2F0ZXIgZm9ybWF0aW9uIHZvbHVtZSBmYWN0b3IiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IlJlc3VsdF9NaXV3IiBBbGlhcz0iV2F0ZXIgVmlzY29zaXR5IiAgICAgICAgICAgICAgIFVuaXQ9Im1QYS5zIiBEZWZhdWx0PSIxIiBNYXg9IjFlKzMwIiBNaW49IjFlLTMwIiBEaWdpdD0iNiIgIERlc2M9InJlc3VsdCB3YXRlciB2aXNjb3NpdHkiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IlJlc3VsdF9DdyIgICBBbGlhcz0iV2F0ZXIgQ29tcHJlc3NpYmlsaXR5IiAgICAgICAgIFVuaXQ9IjEvTVBhIiBEZWZhdWx0PSIwIiBNYXg9IjFlKzMwIiBNaW49IjAiICAgIERpZ2l0PSIxMCIgU2NpZW50aWZpYz0iMSIgRGVzYz0icmVzdWx0IHdhdGVyIGNvbXByZXNzaWJpbGl0eSIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iUmVzdWx0X0JnIiAgIEFsaWFzPSJHYXMgRm9ybWF0aW9uIFZvbHVtZSBGYWN0b3IiICAgVW5pdD0ibTMvbTMiIERlZmF1bHQ9IjEiIE1heD0iMWUrMzAiIE1pbj0iMCIgICAgIERpZ2l0PSI2IiAgRGVzYz0icmVzdWx0IGdhcyBmb3JtYXRpb24gdm9sdW1lIGZhY3RvciIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iUmVzdWx0X01pdWciIEFsaWFzPSJHYXMgVmlzY29zaXR5IiAgICAgICAgICAgICAgICAgVW5pdD0ibVBhLnMiIERlZmF1bHQ9IjEiIE1heD0iMWUrMzAiIE1pbj0iMWUtMzAiIERpZ2l0PSI2IiAgRGVzYz0icmVzdWx0IGdhcyB2aXNjb3NpdHkiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IlJlc3VsdF9DZyIgICBBbGlhcz0iR2FzIENvbXByZXNzaWJpbGl0eSIgICAgICAgICAgIFVuaXQ9IjEvTVBhIiBEZWZhdWx0PSIwIiBNYXg9IjFlKzMwIiBNaW49IjAiICAgIERpZ2l0PSIxMCIgU2NpZW50aWZpYz0iMSIgRGVzYz0icmVzdWx0IGdhcyBjb21wcmVzc2liaWxpdHkiIC8+DQogIDwvUGFyYUdyb3VwPg0KDQogIDwhLS0g5pWP5oSf5oCn57uT5p6c5oyJ6ZiI5YC8562b6YCJ5ZCO5pi+56S677yM56m6562b6YCJ5LiN5Yib5bu65Y+C5pWw5LiK5LiL6ZmQ6KGM44CCIC0tPg0KICA8UGFyYUdyb3VwIE5hbWU9IiIgQWxpYXM9IlJlc3VsdCBQYXJhbWV0ZXJzIj4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iU2Vuc2l0aXZpdHlfUnVuQ291bnQiIEFsaWFzPSJOdW1iZXIgb2YgTW9udGUgQ2FybG8gcnVucyIgVW5pdD0iIiBEZWZhdWx0PSIwIiBNYXg9IjFlKzMwIiBNaW49IjAiIERpZ2l0PSIwIiBEZXNjPSJNb250ZSBDYXJsbyBydW4gY291bnQiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IlNlbnNpdGl2aXR5X1RocmVzaG9sZCIgQWxpYXM9IlRocmVzaG9sZCIgVW5pdD0iTVBhIiBEZWZhdWx0PSIwIiBNYXg9IjFlKzMwIiBNaW49IjAiIERpZ2l0PSI2IiBEZXNjPSJnb29kbmVzcyBvZiBmaXQgdGhyZXNob2xkIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJTZW5zaXRpdml0eV9Ta2luX0xvd2VyIiBBbGlhcz0iU2tpbiAtIExvd2VyIiBVbml0PSIiIERlZmF1bHQ9IjAiIE1heD0iMTAwMCIgTWluPSItMTAwIiBEaWdpdD0iNiIgRGVzYz0iZmlsdGVyZWQgU2tpbiBsb3dlciBib3VuZCIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iU2Vuc2l0aXZpdHlfU2tpbl9IaWdoZXIiIEFsaWFzPSJTa2luIC0gSGlnaGVyIiBVbml0PSIiIERlZmF1bHQ9IjAiIE1heD0iMTAwMCIgTWluPSItMTAwIiBEaWdpdD0iNiIgRGVzYz0iZmlsdGVyZWQgU2tpbiBoaWdoZXIgYm91bmQiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IlNlbnNpdGl2aXR5X0NfTG93ZXIiIEFsaWFzPSJDIC0gTG93ZXIiIFVuaXQ9Im1eMy9NUGEiIERlZmF1bHQ9IjAiIE1heD0iMTAwMCIgTWluPSIwIiBEaWdpdD0iNiIgRGVzYz0iZmlsdGVyZWQgQyBsb3dlciBib3VuZCIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iU2Vuc2l0aXZpdHlfQ19IaWdoZXIiIEFsaWFzPSJDIC0gSGlnaGVyIiBVbml0PSJtXjMvTVBhIiBEZWZhdWx0PSIwIiBNYXg9IjEwMDAiIE1pbj0iMCIgRGlnaXQ9IjYiIERlc2M9ImZpbHRlcmVkIEMgaGlnaGVyIGJvdW5kIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJTZW5zaXRpdml0eV9QaV9Mb3dlciIgQWxpYXM9IlBpIC0gTG93ZXIiIFVuaXQ9Ik1QYSIgRGVmYXVsdD0iNDAiIE1heD0iNTAwIiBNaW49IjAuMSIgRGlnaXQ9IjYiIERlc2M9ImZpbHRlcmVkIFBpIGxvd2VyIGJvdW5kIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJTZW5zaXRpdml0eV9QaV9IaWdoZXIiIEFsaWFzPSJQaSAtIEhpZ2hlciIgVW5pdD0iTVBhIiBEZWZhdWx0PSI0MCIgTWF4PSI1MDAiIE1pbj0iMC4xIiBEaWdpdD0iNiIgRGVzYz0iZmlsdGVyZWQgUGkgaGlnaGVyIGJvdW5kIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJTZW5zaXRpdml0eV9LX0xvd2VyIiBBbGlhcz0iayAtIExvd2VyIiBVbml0PSJtRCIgRGVmYXVsdD0iMjUiIE1heD0iMTAwMDAiIE1pbj0iMCIgRGlnaXQ9IjYiIERlc2M9ImZpbHRlcmVkIEsgbG93ZXIgYm91bmQiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IlNlbnNpdGl2aXR5X0tfSGlnaGVyIiBBbGlhcz0iayAtIEhpZ2hlciIgVW5pdD0ibUQiIERlZmF1bHQ9IjI1IiBNYXg9IjEwMDAwIiBNaW49IjAiIERpZ2l0PSI2IiBEZXNjPSJmaWx0ZXJlZCBLIGhpZ2hlciBib3VuZCIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iU2Vuc2l0aXZpdHlfaF9Mb3dlciIgQWxpYXM9ImggLSBMb3dlciIgVW5pdD0ibSIgRGVmYXVsdD0iMTAiIE1heD0iMTAwMDAiIE1pbj0iMWUtMDUiIERpZ2l0PSI2IiBEZXNjPSJmaWx0ZXJlZCBoIGxvd2VyIGJvdW5kIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJTZW5zaXRpdml0eV9oX0hpZ2hlciIgQWxpYXM9ImggLSBIaWdoZXIiIFVuaXQ9Im0iIERlZmF1bHQ9IjEwIiBNYXg9IjEwMDAwIiBNaW49IjFlLTA1IiBEaWdpdD0iNiIgRGVzYz0iZmlsdGVyZWQgaCBoaWdoZXIgYm91bmQiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IlNlbnNpdGl2aXR5X3BoaV9Mb3dlciIgQWxpYXM9Is+GIC0gTG93ZXIiIFVuaXQ9IiIgRGVmYXVsdD0iMC4xIiBNYXg9IjEiIE1pbj0iMWUtMDUiIERpZ2l0PSI2IiBEZXNjPSJmaWx0ZXJlZCBwaGkgbG93ZXIgYm91bmQiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IlNlbnNpdGl2aXR5X3BoaV9IaWdoZXIiIEFsaWFzPSLPhiAtIEhpZ2hlciIgVW5pdD0iIiBEZWZhdWx0PSIwLjEiIE1heD0iMSIgTWluPSIxZS0wNSIgRGlnaXQ9IjYiIERlc2M9ImZpbHRlcmVkIHBoaSBoaWdoZXIgYm91bmQiIC8+DQogICAgPCEtLSDnrKzlm5vnp43vvJrmjInlkIzkuIDor6/lt67pmIjlgLznrZvpgInlkITnu4Tmi5/lkIjmnIDkvJjlgLzjgIIgLS0+DQogICAgPFBhcmFJdGVtIE5hbWU9IlNlbnNpdGl2aXR5X0ZpdF9LX01pbmltdW0iIEFsaWFzPSJQZXJtZWFiaWxpdHkgLSBNaW5pbXVtIiBVbml0PSJtRCIgRGVmYXVsdD0iMjUiIE1heD0iMTAwMDAiIE1pbj0iMCIgRGlnaXQ9IjYiIERlc2M9Iuetm+mAieWQjuaLn+WQiOWPguaVsOa4l+mAj+eOh+acgOWwj+WAvCIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iU2Vuc2l0aXZpdHlfRml0X0tfTWF4aW11bSIgQWxpYXM9IlBlcm1lYWJpbGl0eSAtIE1heGltdW0iIFVuaXQ9Im1EIiBEZWZhdWx0PSIyNSIgTWF4PSIxMDAwMCIgTWluPSIwIiBEaWdpdD0iNiIgRGVzYz0i562b6YCJ5ZCO5ouf5ZCI5Y+C5pWw5riX6YCP546H5pyA5aSn5YC8IiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJTZW5zaXRpdml0eV9GaXRfU2tpbl9NaW5pbXVtIiBBbGlhcz0iU2tpbiAtIE1pbmltdW0iIFVuaXQ9IiIgRGVmYXVsdD0iMCIgTWF4PSIxMDAwIiBNaW49Ii0xMDAiIERpZ2l0PSI2IiBEZXNjPSLnrZvpgInlkI7mi5/lkIjlj4LmlbDooajnmq7ns7vmlbDmnIDlsI/lgLwiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IlNlbnNpdGl2aXR5X0ZpdF9Ta2luX01heGltdW0iIEFsaWFzPSJTa2luIC0gTWF4aW11bSIgVW5pdD0iIiBEZWZhdWx0PSIwIiBNYXg9IjEwMDAiIE1pbj0iLTEwMCIgRGlnaXQ9IjYiIERlc2M9Iuetm+mAieWQjuaLn+WQiOWPguaVsOihqOearuezu+aVsOacgOWkp+WAvCIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iU2Vuc2l0aXZpdHlfRml0X0NfTWluaW11bSIgQWxpYXM9IldlbGxib3JlIHN0b3JhZ2UgLSBNaW5pbXVtIiBVbml0PSJtXjMvTVBhIiBEZWZhdWx0PSIwIiBNYXg9IjEwMDAiIE1pbj0iMCIgRGlnaXQ9IjYiIERlc2M9Iuetm+mAieWQjuaLn+WQiOWPguaVsOS6leetkuWCqOmbhuezu+aVsOacgOWwj+WAvCIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iU2Vuc2l0aXZpdHlfRml0X0NfTWF4aW11bSIgQWxpYXM9IldlbGxib3JlIHN0b3JhZ2UgLSBNYXhpbXVtIiBVbml0PSJtXjMvTVBhIiBEZWZhdWx0PSIwIiBNYXg9IjEwMDAiIE1pbj0iMCIgRGlnaXQ9IjYiIERlc2M9Iuetm+mAieWQjuaLn+WQiOWPguaVsOS6leetkuWCqOmbhuezu+aVsOacgOWkp+WAvCIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iU2Vuc2l0aXZpdHlfRml0X3BoaV9NaW5pbXVtIiBBbGlhcz0iUG9yb3NpdHkgLSBNaW5pbXVtIiBVbml0PSIiIERlZmF1bHQ9IjAuMSIgTWF4PSIxIiBNaW49IjFlLTA1IiBEaWdpdD0iNiIgRGVzYz0i562b6YCJ5ZCO5ouf5ZCI5Y+C5pWw5a2U6ZqZ5bqm5pyA5bCP5YC8IiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJTZW5zaXRpdml0eV9GaXRfcGhpX01heGltdW0iIEFsaWFzPSJQb3Jvc2l0eSAtIE1heGltdW0iIFVuaXQ9IiIgRGVmYXVsdD0iMC4xIiBNYXg9IjEiIE1pbj0iMWUtMDUiIERpZ2l0PSI2IiBEZXNjPSLnrZvpgInlkI7mi5/lkIjlj4LmlbDlrZTpmpnluqbmnIDlpKflgLwiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IlNlbnNpdGl2aXR5X0ZpdF9EZmNfTWluaW11bSIgQWxpYXM9IkZyYWN0dXJlIGNvbmR1Y3Rpdml0eSAtIE1pbmltdW0iIFVuaXQ9Im1ELm0iIERlZmF1bHQ9IjEwMDAiIE1heD0iMWUrMzAiIE1pbj0iMCIgRGlnaXQ9IjYiIERlc2M9Iuetm+mAieWQjuaLn+WQiOWPguaVsOijgue8neWvvOa1geiDveWKm+acgOWwj+WAvCIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iU2Vuc2l0aXZpdHlfRml0X0RmY19NYXhpbXVtIiBBbGlhcz0iRnJhY3R1cmUgY29uZHVjdGl2aXR5IC0gTWF4aW11bSIgVW5pdD0ibUQubSIgRGVmYXVsdD0iMTAwMCIgTWF4PSIxZSszMCIgTWluPSIwIiBEaWdpdD0iNiIgRGVzYz0i562b6YCJ5ZCO5ouf5ZCI5Y+C5pWw6KOC57yd5a+85rWB6IO95Yqb5pyA5aSn5YC8IiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJTZW5zaXRpdml0eV9GaXRfRnJhY3R1cmVIYWxmTGVuZ3RoX01pbmltdW0iIEFsaWFzPSJGcmFjdHVyZSBoYWxmIGxlbmd0aCAtIE1pbmltdW0iIFVuaXQ9Im0iIERlZmF1bHQ9IjUwIiBNYXg9IjEwMDAwIiBNaW49IjFlLTA1IiBEaWdpdD0iNiIgRGVzYz0i562b6YCJ5ZCO5ouf5ZCI5Y+C5pWw6KOC57yd5Y2K6ZW/5pyA5bCP5YC8IiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJTZW5zaXRpdml0eV9GaXRfRnJhY3R1cmVIYWxmTGVuZ3RoX01heGltdW0iIEFsaWFzPSJGcmFjdHVyZSBoYWxmIGxlbmd0aCAtIE1heGltdW0iIFVuaXQ9Im0iIERlZmF1bHQ9IjUwIiBNYXg9IjEwMDAwIiBNaW49IjFlLTA1IiBEaWdpdD0iNiIgRGVzYz0i562b6YCJ5ZCO5ouf5ZCI5Y+C5pWw6KOC57yd5Y2K6ZW/5pyA5aSn5YC8IiAvPg0KICA8L1BhcmFHcm91cD4NCg0KPC9Sb290Pg0K \ No newline at end of file diff --git a/Bin/Config/Lang/cn/nmNum_cn.qm b/Bin/Config/Lang/cn/nmNum_cn.qm index 619d2e75..40d61a60 100644 Binary files a/Bin/Config/Lang/cn/nmNum_cn.qm and b/Bin/Config/Lang/cn/nmNum_cn.qm differ diff --git a/Bin/Config/Lang/cn/nmNum_cn.ts b/Bin/Config/Lang/cn/nmNum_cn.ts index 34e4bd06..d67a0853 100644 --- a/Bin/Config/Lang/cn/nmNum_cn.ts +++ b/Bin/Config/Lang/cn/nmNum_cn.ts @@ -7388,6 +7388,22 @@ Average pressure in contour: %2 MPa nmWxSensitive + + Result plots + 结果图 + + + Loglog plot + 双对数图 + + + History plot + 历史曲线 + + + Histogram + 直方图 + Sensitivity 敏感性分析 @@ -8738,6 +8754,10 @@ Average pressure in contour: %2 MPa nmWxForecast + + Result plots + 结果图 + Forecast 预测 diff --git a/Include/nmNum/nmSubWnd/nmSubWndMain.h b/Include/nmNum/nmSubWnd/nmSubWndMain.h index e90f2b6c..36f26593 100644 --- a/Include/nmNum/nmSubWnd/nmSubWndMain.h +++ b/Include/nmNum/nmSubWnd/nmSubWndMain.h @@ -22,6 +22,7 @@ class nmCalculationDllPebiSolverTask; class nmWxSensitive; class nmWxForecast; class iSubWndFitting; +class QDialog; class QWidget; class QObject; @@ -170,9 +171,11 @@ class NM_SUB_WND_EXPORT nmSubWndMain : public iSubWndBaseFit { void onForecastTaskReady(nmWxForecast* dialog, nmCalculationDllPebiSolverTask* task); void onAuxiliarySolverTaskFinished(); void onAuxiliarySolverTaskDestroyed(); - /** @brief 在框架已有的敏感性子窗口叠加显示本分析的双对数结果。 */ + /** @brief 在独立对话框中显示本分析的敏感性结果。 */ void onShowSensitiveResults(); - // 预测结果复用所属分析内的 MDI 子窗口,模型变化时移除旧结果。 + // 输入窗口菜单按需打开指定结果图。 + void onShowSensitiveResult(int plotType); + // 预测结果复用所属分析的独立对话框。 void onShowForecastResult(); void onForecastDataChanged(); // 只读结果曲线共用框架数据表,不开放拖动编辑。 @@ -293,7 +296,9 @@ class NM_SUB_WND_EXPORT nmSubWndMain : public iSubWndBaseFit { bool initloglog(QVector> & vvecLogPreData, QVector& vecDescs,bool isHistoryData); // 压力历史曲线数据 bool initPreHistory(QVector> & vvecHistoryData, QVector& vecDescs,bool isHistoryData); - // 在分析页面内同步敏感性压力/流量历史图。 + // 创建本分析所属的非模态结果对话框。 + QDialog* createResultDialog(const QString& name, const QString& title); + // 在独立对话框内同步敏感性压力/流量历史图。 void updateSensitiveHistoryPlot(); // 各结果图使用独立的 Show 按钮打开曲线显示表格。 void installSensitiveShow(QWidget* host); diff --git a/Include/nmNum/nmSubWxs/nmParameterField.h b/Include/nmNum/nmSubWxs/nmParameterField.h index 1b9c9b20..44fefde8 100644 --- a/Include/nmNum/nmSubWxs/nmParameterField.h +++ b/Include/nmNum/nmSubWxs/nmParameterField.h @@ -119,6 +119,9 @@ public: /** @brief 返回数值编辑列的统一最小宽度。 */ static int editorMinimumWidth(); + /** @brief 将单位别名及上标写法统一到框架单位表中的名称。 */ + static QString resolveUnitSpelling(const QString& sUnit); + /** @brief 返回单位列的统一最小宽度。 */ static int unitMinimumWidth(); diff --git a/Include/nmNum/nmSubWxs/nmWxAutomaticFitting.h b/Include/nmNum/nmSubWxs/nmWxAutomaticFitting.h index 0c3d4172..cb5ffd8a 100644 --- a/Include/nmNum/nmSubWxs/nmWxAutomaticFitting.h +++ b/Include/nmNum/nmSubWxs/nmWxAutomaticFitting.h @@ -37,6 +37,7 @@ public: const QStringList& sampledParameters = QStringList()); ~nmWxAutomaticFitting(); virtual QSize sizeHint() const; + void reloadSensitivitySettings(const QStringList& sampledParameters); private slots: void onSelectAll(bool checked); diff --git a/Include/nmNum/nmSubWxs/nmWxForecast.h b/Include/nmNum/nmSubWxs/nmWxForecast.h index 2ab3d0de..6895b9fc 100644 --- a/Include/nmNum/nmSubWxs/nmWxForecast.h +++ b/Include/nmNum/nmSubWxs/nmWxForecast.h @@ -33,9 +33,11 @@ public: signals: void sigForecastTaskReady(nmWxForecast* dialog, nmCalculationDllPebiSolverTask* task); void sigForecastCancelRequested(); + void sigShowForecastResult(); public slots: void reject(); + void reloadInputData(); protected: void closeEvent(QCloseEvent* event); @@ -59,7 +61,7 @@ protected: void onCancelClicked(); void onForecastFinished(); void onModelChanged(); - void saveDataToManager(); + void updateResultButton(); // Table edit void onPressureCellChanged(int row, int column); @@ -75,6 +77,7 @@ private: void setupUI(); void setupConnections(); void loadDataFromManager(); + void saveDataToManager(); void updateParametersForOption(); void updateUIFromData(); void updateDataFromUI(); @@ -142,6 +145,7 @@ private: QHBoxLayout *m_buttonLayout; QPushButton *m_loadDataButton; QPushButton *m_generateButton; + QPushButton *m_resultPlotButton; QPushButton *m_cancelButton; // Table diff --git a/Include/nmNum/nmSubWxs/nmWxNumericalDesign.h b/Include/nmNum/nmSubWxs/nmWxNumericalDesign.h index a13fd4d0..0ddc30b4 100644 --- a/Include/nmNum/nmSubWxs/nmWxNumericalDesign.h +++ b/Include/nmNum/nmSubWxs/nmWxNumericalDesign.h @@ -77,6 +77,8 @@ signals: void sigGenerateClicked(); // 点击生成按钮时发出的信号 // 敏感性批量任务交给所属主窗口,复用普通求解进度框。 void sigSensitivityTaskReady(nmWxSensitive* dialog, nmCalculationDllPebiSolverTask* task); + void sigShowSensitivityResult(int plotType); + void sigShowForecastResult(); void sigIncludeWells(); // 包含其他井后刷新参数栏的信号 /** @brief 用户切换结果井时发送快照中的稳定井 UUID。 */ void sigResultWellChanged(const QString& sWellInstanceId); @@ -229,6 +231,7 @@ private: QPushButton* m_pForecastBtn; QPointer m_pForecastDialog; ///< 每个分析面板复用自己的预测输入窗口。 QPushButton* m_pSensitiveBtn; + QPointer m_pSensitiveDialog; ///< 每个分析面板复用自己的敏感性分析输入窗口。 QHBoxLayout* m_pGenerateLayout; // 主布局 diff --git a/Include/nmNum/nmSubWxs/nmWxSensitive.h b/Include/nmNum/nmSubWxs/nmWxSensitive.h index a75774ac..485de2f3 100644 --- a/Include/nmNum/nmSubWxs/nmWxSensitive.h +++ b/Include/nmNum/nmSubWxs/nmWxSensitive.h @@ -34,12 +34,14 @@ class NM_SUB_WXS_EXPORT nmWxSensitivityHistogramOptions : public iDlgBase public: nmWxSensitivityHistogramOptions(const QSharedPointer& results, int bins, QWidget* parent); + void setResults(const QSharedPointer& results); signals: void settingsChanged(int bins, int variable); private slots: void onApply(); void onAccept(); private: + QTableView* m_table; QSpinBox* m_bins; QComboBox* m_variable; }; @@ -50,6 +52,7 @@ class NM_SUB_WXS_EXPORT nmWxSensitivityScatter : public iDlgBase public: nmWxSensitivityScatter(const QSharedPointer& results, double baseError, QWidget* parent = nullptr); + void setResults(const QSharedPointer& results, double baseError); signals: void filterChanged(); protected: @@ -83,6 +86,7 @@ public: nmWxSensitivityShow(const QSharedPointer& results, iGuiPlot* plot, QWidget* parent); void done(int result) override; + void setResults(const QSharedPointer& results); private slots: void onApply(); @@ -100,14 +104,17 @@ class NM_SUB_WXS_EXPORT nmWxSensitive : public iDlgBase Q_OBJECT public: + enum ResultPlot { LoglogResult, HistoryResult, HistogramResult }; explicit nmWxSensitive(QWidget *parent = 0, nmDataAnalyzeManager* manager = nullptr); ~nmWxSensitive(); // 主窗口接管普通求解进度框后,才隐藏参数窗口并启动批量任务。 void startSensitivityCalculation(); + void reloadInputData(); signals: void sigSensitivityTaskReady(nmWxSensitive* dialog, nmCalculationDllPebiSolverTask* task); void sigSensitivityCancelRequested(); + void sigShowSensitivityResult(int plotType); public slots: void reject() override; @@ -123,12 +130,14 @@ protected: void onTreeItemClicked(QTreeWidgetItem *item, int column); void onVariableParamChanged(); void onSamplingEditingFinished(); + void onSamplingUnitChanged(); void onTableCellClicked(int row, int column); void onTreeItemChanged(QTreeWidgetItem *item, int column); void onPreviewClicked(); void onPreviewScrollAction(int action); void onSensitivityFinished(); void onResultsChanged(); + void onResultPlotTriggered(QAction* action); void onModelResultChanged(); private: @@ -156,6 +165,8 @@ private: QStackedWidget *detailStack; QLabel *modelCountLabel; QSpinBox *m_monteCarloCount; + QPushButton *m_resultPlotsButton; + QAction *m_histogramResultAction; QPushButton *generateButton; QPushButton *cancelButton; QPushButton *previewButton; @@ -168,7 +179,7 @@ private: QList m_minSpins; QList m_maxSpins; QList m_valueTables; - QList m_unitLabels; + QList m_unitCombos; QList m_numLabels, m_minLabels, m_maxLabels; QList m_distributionCombos; QList m_distributionPanels; @@ -176,8 +187,10 @@ private: // 跟踪当前选中的值索引 int m_selectedValueIndex; + QSharedPointer m_improveSettingsDraft; bool m_loading; nmDataAnalyzeManager* m_pDataManager; + const nmDataSensitive* m_sourceData; ///< 识别项目读取后数据对象的替换,不持有其所有权。 SensitivityRunsView* m_previewView; nmCalculationDllPebiSolverTask* m_pSensitivityTask; bool m_calculationRunning; diff --git a/Src/nmNum/nmData/nmDataAnalyzeManager.cpp b/Src/nmNum/nmData/nmDataAnalyzeManager.cpp index f2358f35..e0b8f5ec 100644 --- a/Src/nmNum/nmData/nmDataAnalyzeManager.cpp +++ b/Src/nmNum/nmData/nmDataAnalyzeManager.cpp @@ -4838,8 +4838,8 @@ bool nmDataAnalyzeManager::setCurrentResultWellInstanceId( return true; } + // 仅切换查看井,不通知快照变更,避免清理预测和敏感性分析的数据及窗口。 m_sCurrentResultWellInstanceId = sValidatedWellInstanceId; - emit sigPebiResultSnapshotChanged(); return true; } diff --git a/Src/nmNum/nmSubWnd/nmSubWndMain.cpp b/Src/nmNum/nmSubWnd/nmSubWndMain.cpp index 54a07f3f..17e160b4 100644 --- a/Src/nmNum/nmSubWnd/nmSubWndMain.cpp +++ b/Src/nmNum/nmSubWnd/nmSubWndMain.cpp @@ -78,7 +78,7 @@ #include #include #include -#include +#include #include "ZxMdiArea.h" #include "nmSingalCenter.h" @@ -130,6 +130,32 @@ void clearResultCurveDataTables(iGuiPlot* plot) } } +// 结果替换时保留窗口,清理旧批次引用、曲线与框架表格,随后按需重绘。 +void resetResultDialog(QDialog* window) +{ + if(!window) return; + // 先恢复最小化状态再隐藏,避免隐藏后调整尺寸使系统重新显示空白窗口。 + if(window->isMinimized()) + window->setWindowState(window->windowState() & ~Qt::WindowMinimized); + window->hide(); + foreach(iGuiPlot* plot, window->findChildren()) clearResultCurveDataTables(plot); + foreach(nmWxSensitivityShow* dialog, window->findChildren()) + dialog->setResults(QSharedPointer()); + foreach(nmWxSensitivityHistogramOptions* dialog, window->findChildren()) + dialog->setResults(QSharedPointer()); + foreach(nmWxSensitivityScatter* dialog, window->findChildren()) + dialog->setResults(QSharedPointer(), -1.0); + foreach(iGuiPlot* plot, window->findChildren()) { + clearResultCurveDataTables(plot); + for(int i = plot->m_pPlot->getObjCount() - 1; i >= 0; --i) + if(qobject_cast(plot->m_pPlot->getObjByIndex(i))) plot->m_pPlot->removeObjByIndex(i); + plot->clearUndoStack(); + plot->setCurveData(QVector()); + plot->runUpdate(); + } + window->setProperty("nmResultDirty", true); +} + QSet hiddenSensitiveCurves(iGuiPlot* plot) { // 刷新同一批次或重新打开窗口时保留本图的显示选择。 @@ -334,6 +360,11 @@ void nmSubWndMain::onPebiResultSnapshotChanged() return; } + // 项目读取或结果井切换后清理旧图,保留数据,等待设置窗口请求显示。 + const char* names[] = { "nmForecastResult", "nmSensitivityLoglog", "nmSensitivityHistory", "nmSensitivityHistogram" }; + for(int i = 0; i < 4; ++i) + resetResultDialog(pSubWndFitting->findChild(names[i])); + QSharedPointer pSnapshot = pDataManager->getPebiResultSnapshot(); if(pSnapshot.isNull()) { @@ -343,25 +374,6 @@ void nmSubWndMain::onPebiResultSnapshotChanged() const QString sSnapshotId = pSnapshot->getSnapshotId(); if(sSnapshotId == m_sObservedPebiResultSnapshotId) { - // 切换结果井时关闭上一口井的敏感性窗口及附属表格,保留批次数据供再次查看。 - ZxMdiArea* area = pSubWndFitting->m_pMdiArea; - if(area) { - iGuiPlot* loglog = pSubWndFitting->getPlotByTag(s_Tag_ChartSensitivity); - bool closed = false; - foreach(QMdiSubWindow* window, area->subWindowList()) { - if(window->objectName() != "nmSensitivityHistory" && - window->objectName() != "nmSensitivityHistogram" && - !(loglog && window->isAncestorOf(loglog))) continue; - foreach(iGuiPlot* plot, window->findChildren()) - clearResultCurveDataTables(plot); - foreach(QDialog* dialog, window->findChildren()) { - if(dialog->isWindow()) dialog->close(); - } - window->close(); - closed = true; - } - if(closed && area->isVisible()) area->relayoutSubWnds(); - } // 同一快照内切换结果井仍由 onWellSelected() 处理,不重复刷新全部结果页面。 return; } @@ -1961,15 +1973,29 @@ void nmSubWndMain::onForecastDataChanged() m_pResultRefreshFitting->setModified(true); } +QDialog* nmSubWndMain::createResultDialog(const QString& name, const QString& title) +{ + // 关闭只隐藏,窗口及绘图控件由所属分析统一销毁。 + QDialog* dialog = new QDialog(m_pResultRefreshFitting.data(), + Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint); + dialog->setObjectName(name); + dialog->setWindowTitle(title); + dialog->setAttribute(Qt::WA_DeleteOnClose, false); + dialog->resize(900, 650); + QVBoxLayout* layout = new QVBoxLayout(dialog); + layout->setContentsMargins(0, 0, 0, 0); + dialog->installEventFilter(this); + return dialog; +} + void nmSubWndMain::onShowForecastResult() { // 使用面板绑定的分析页面,切换活动分析不会改变预测结果的归属。 iSubWndFitting* fitting = m_pResultRefreshFitting.data(); nmDataAnalyzeManager* manager = m_pResultRefreshDataManager.data(); - if(!fitting || !fitting->m_pMdiArea || !manager || + if(!fitting || !manager || nmDataAnalyzeManager::findManagerByFitting(fitting) != manager) return; - ZxMdiArea* area = fitting->m_pMdiArea; - QMdiSubWindow* window = area->findChild("nmForecastResult"); + QDialog* window = fitting->findChild("nmForecastResult"); const QSharedPointer result = manager->getForecastData() ? manager->getForecastData()->getResult() : QSharedPointer(); const QSharedPointer snapshot = manager->getPebiResultSnapshot(); @@ -1977,12 +2003,7 @@ void nmSubWndMain::onShowForecastResult() result->snapshotId != snapshot->getSnapshotId() || result->wellInstanceId != manager->getCurrentResultWellInstanceId()) { // 基础结果或结果井切换后清除旧窗口;模型参数编辑不影响上次预测的显示。 - if(window) { - foreach(iGuiPlot* plot, window->findChildren()) clearResultCurveDataTables(plot); - area->removeSubWindow(window); - delete window; - if(area->isVisible()) area->relayoutSubWnds(); - } + resetResultDialog(window); return; } const QVector& times = result->times; @@ -1991,10 +2012,9 @@ void nmSubWndMain::onShowForecastResult() const QVector& rates = result->rates; const bool created = window == nullptr; if(created) { - // 结果页面由 MDI 承载,关闭预测输入对话框不销毁结果。 - QWidget* page = new QWidget; - QVBoxLayout* layout = new QVBoxLayout(page); - layout->setContentsMargins(0, 0, 0, 0); + window = createResultDialog("nmForecastResult", nmWxForecast::tr("Forecast")); + QWidget* page = window; + QVBoxLayout* layout = qobject_cast(window->layout()); QSplitter* charts = new QSplitter(Qt::Vertical, page); charts->setObjectName("nmForecastCharts"); charts->setChildrenCollapsible(false); @@ -2029,9 +2049,6 @@ void nmSubWndMain::onShowForecastResult() connect(plot->getAxisOf(0), SIGNAL(sigRangeChanged(double,double,bool,bool)), this, SLOT(syncForecastTimeAxis(double,double,bool,bool))); } - window = area->addSubWindow(page); - window->setObjectName("nmForecastResult"); - window->setAttribute(Qt::WA_DeleteOnClose, false); } // 与预测输入窗口共用标题译文,不附加井名。 window->setWindowTitle(nmWxForecast::tr("Forecast")); @@ -2103,12 +2120,11 @@ void nmSubWndMain::onShowForecastResult() // 时间刻度及标题只在下图显示,上图仍保留横轴数据与同步关系。 plot->getAxisOf(0)->setMinimizeAxis(i == 0); } - const bool restore = window->isHidden(); - window->widget()->show(); - window->show(); - // 隐藏的分析页交给框架显示事件布局,避免此时重排把结果重新隐藏。 - if((created || restore) && area->isVisible()) area->relayoutSubWnds(); - area->setActiveSubWindow(window); + // 再次生成时恢复已最小化的结果窗口,正常或最大化状态保持不变。 + if(window->isMinimized()) window->showNormal(); + else window->show(); + window->raise(); + window->activateWindow(); QTimer::singleShot(0, this, SLOT(fitForecastViews())); } @@ -2135,7 +2151,25 @@ void nmSubWndMain::onReadonlyCurveDoubleClicked( bool nmSubWndMain::eventFilter(QObject* watched, QEvent* event) { - // 子窗口缩放、重新显示均在内部控件完成尺寸更新后再适配。 + // 最小化时先恢复窗口状态,再交给默认关闭流程隐藏,避免复用时丢失正常尺寸。 + QDialog* dialog = qobject_cast(watched); + if(dialog && event->type() == QEvent::Close && dialog->isMinimized()) + dialog->setWindowState(dialog->windowState() & ~Qt::WindowMinimized); + // 关闭结果对话框时同步关闭其曲线数据表、Show 和统计设置窗口。 + if((event->type() == QEvent::Close || event->type() == QEvent::Hide) && + qobject_cast(watched)) { + foreach(iGuiPlot* plot, watched->findChildren()) + clearResultCurveDataTables(plot); + foreach(QDialog* dialog, watched->findChildren()) + if(dialog->isWindow()) dialog->close(); + } + // 独立窗口不再经过 MDI 的画布适配,显示和缩放时适配自己的绘图区。 + if(dialog && (event->type() == QEvent::Resize || event->type() == QEvent::Show)) { + dialog->layout()->activate(); + foreach(iGuiPlot* plot, dialog->findChildren()) + plot->m_pPlotView->setZoomMode(ZxRenderView::eZoomFitWindow, true); + } + // 对话框缩放、重新显示均在内部控件完成尺寸更新后再适配。 if(watched->objectName() == "nmForecastCharts" && (event->type() == QEvent::Resize || event->type() == QEvent::Show)) QTimer::singleShot(0, this, SLOT(fitForecastViews())); @@ -2146,8 +2180,8 @@ void nmSubWndMain::fitForecastViews() { // 只适配图形画布的显示尺寸,不改变用户选定的时间和压力范围。 iSubWndFitting* fitting = m_pResultRefreshFitting.data(); - if(!fitting || !fitting->m_pMdiArea) return; - QMdiSubWindow* window = fitting->m_pMdiArea->findChild("nmForecastResult"); + if(!fitting) return; + QDialog* window = fitting->findChild("nmForecastResult"); if(!window) return; foreach(iGuiPlot* plot, window->findChildren()) plot->m_pPlotView->setZoomMode(ZxRenderView::eZoomFitWindow, true); @@ -2157,8 +2191,8 @@ void nmSubWndMain::syncForecastTimeAxis(double minimum, double maximum, bool rec { // 只同步本分析预测图的横轴;阻断回传,避免两张图相互触发范围更新。 iSubWndFitting* fitting = m_pResultRefreshFitting.data(); - if(!fitting || !fitting->m_pMdiArea) return; - QMdiSubWindow* window = fitting->m_pMdiArea->findChild("nmForecastResult"); + if(!fitting) return; + QDialog* window = fitting->findChild("nmForecastResult"); if(!window) return; iGuiPlot* rate = window->findChild("nmForecastRate"); iGuiPlot* pressure = window->findChild("nmForecastPressure"); @@ -2173,48 +2207,62 @@ void nmSubWndMain::syncForecastTimeAxis(double minimum, double maximum, bool rec void nmSubWndMain::onShowSensitiveResults() { - // 使用固定所属分析的窗口与数据,不能把结果画到当前活动的其他分析中。 nmDataAnalyzeManager* manager = m_pResultRefreshDataManager.data(); iSubWndFitting* fitting = m_pResultRefreshFitting.data(); - if(!manager || !fitting || !manager->getSensitiveData()) return; - // 新批次或清空结果时同步移除上一批的上下限分组。 + if(!manager || !fitting) return; + // 新批次先清理已有窗口的旧数据,默认只重绘并显示双对数图。 + const char* names[] = { "nmSensitivityLoglog", "nmSensitivityHistory", "nmSensitivityHistogram" }; + for(int i = 0; i < 3; ++i) { + QDialog* window = fitting->findChild(names[i]); + resetResultDialog(window); + } onSensitiveFilterChanged(); - updateSensitiveHistoryPlot(); - updateSensitiveHistogramPlot(); - QSharedPointer result = manager->getSensitiveData()->getResults(); - iGuiPlot* plot = fitting->getPlotByTag(s_Tag_ChartSensitivity); - if(plot) clearResultCurveDataTables(plot); - if(result.isNull()) { - // 新模型已丢弃旧批次,同时清除图元与撤销记录,避免窗口恢复或保存后残留旧曲线。 - if(plot) { - for(int i = plot->m_pPlot->getObjCount() - 1; i >= 0; --i) { - if(qobject_cast(plot->m_pPlot->getObjByIndex(i))) - plot->m_pPlot->removeObjByIndex(i); - } - plot->clearUndoStack(); - plot->setCurveData(QVector()); - plot->runUpdate(); - QMdiSubWindow* subWindow = nullptr; - for(QWidget* parent = plot->parentWidget(); parent && !subWindow; parent = parent->parentWidget()) - subWindow = qobject_cast(parent); - if(subWindow) subWindow->close(); - else plot->hide(); - } - if(sender() == manager) fitting->setModified(true); + onShowSensitiveResult(nmWxSensitive::LoglogResult); + if(sender() == manager) fitting->setModified(true); +} + +void nmSubWndMain::onShowSensitiveResult(int plotType) +{ + // 仅从数据中心读取已有批次,已打开的图直接恢复并激活,不重复绘制。 + nmDataAnalyzeManager* manager = m_pResultRefreshDataManager.data(); + iSubWndFitting* fitting = m_pResultRefreshFitting.data(); + if(!manager || !fitting || !manager->getSensitiveData()) return; + const QSharedPointer result = manager->getSensitiveData()->getResults(); + if(result.isNull() || plotType < nmWxSensitive::LoglogResult || + plotType > nmWxSensitive::HistogramResult) return; + if(plotType == nmWxSensitive::HistogramResult && result->m_calcType != nmDataSensitive::CALC_MONTE_CARLO) return; + const char* names[] = { "nmSensitivityLoglog", "nmSensitivityHistory", "nmSensitivityHistogram" }; + QDialog* window = fitting->findChild(names[plotType]); + if(window && !window->property("nmResultDirty").toBool()) { + if(window->isMinimized()) window->showNormal(); + else window->show(); + window->raise(); + window->activateWindow(); + return; + } + if(plotType == nmWxSensitive::HistoryResult) { + updateSensitiveHistoryPlot(); return; } - const bool created = plot == nullptr; - // 通用取窗接口未实现敏感性类型,直接复用框架已有的内部 MDI 创建函数。 - if(created) plot = fitting->initSensitivityPlot(); - if(!plot) { - QMessageBox::warning(fitting, nmWxSensitive::tr("Sensitivity"), - tr("Failed to create sensitivity plot.")); + if(plotType == nmWxSensitive::HistogramResult) { + updateSensitiveHistogramPlot(); return; } + // 与预测一致,直接在结果对话框内创建框架绘图控件,不经过主界面 MDI。 + if(!window) { + window = createResultDialog("nmSensitivityLoglog", tr("Sensitivity loglog plot")); + iGuiPlot* plot = new iGuiPlot(true, window); + plot->initUI(tr("Sensitivity loglog plot")); + plot->m_pPlotView->setSimpleMode(true); + plot->setAxisX(tr("Time"), "hr"); + plot->setAxisY(tr("Pressure"), "MPa"); + plot->m_pPlot->setBKColor(Qt::white); + window->layout()->addWidget(plot); + } + iGuiPlot* plot = window->findChild(); connect(plot, SIGNAL(sigDoubleClicked(ZxPlot*,ZxObjBase*,const QPointF&,bool&)), this, SLOT(onReadonlyCurveDoubleClicked(ZxPlot*,ZxObjBase*,const QPointF&,bool&)), Qt::UniqueConnection); installSensitiveShow(plot); - const QSet hidden = sender() == manager ? QSet() : hiddenSensitiveCurves(plot); QVector curves; QVector > history = result->m_vecHistoryLogLog; if(history.size() == 3 && history[0].size() == history[1].size() && @@ -2268,78 +2316,44 @@ void nmSubWndMain::onShowSensitiveResults() plot->setAxisXYLog(true, 1); if(!result->m_sAxisXName.isEmpty()) plot->setAxisX(result->m_sAxisXName, result->m_sAxisXUnit); if(!result->m_sAxisYName.isEmpty()) plot->setAxisY(result->m_sAxisYName, result->m_sAxisYUnit); - // 框架刷新只创建或更新传入曲线,不删除缺席曲线,先移除已隐藏或上一批残留的图元。 - QSet visibleNames; - for(int i = 0; i < curves.size(); ++i) visibleNames.insert(curves[i].m_sCurveName); - bool removed = false; - for(int i = plot->m_pPlot->getObjCount() - 1; i >= 0; --i) { - ZxObjCurve* curve = qobject_cast(plot->m_pPlot->getObjByIndex(i)); - if(curve && !visibleNames.contains(curve->getName())) { - plot->m_pPlot->removeObjByIndex(i); - removed = true; - } - } - // 清理删除曲线相关的撤销记录,避免后续操作恢复已经隐藏的图元。 - if(removed) plot->clearUndoStack(); plot->setCurveData(curves); plot->runUpdate(); - for(int i = 0; i < curves.size(); ++i) - if(ZxObjCurve* curve = plot->getCurve(curves[i].m_sCurveName)) - curve->setVisible(!hidden.contains(curve->getName())); plot->setReadOnly(true); plot->freshAxisScales(true, false); - // 只有新建或恢复窗口时才重新调整内部布局。 - QMdiSubWindow* subWindow = nullptr; - for(QWidget* parent = plot->parentWidget(); parent && !subWindow; parent = parent->parentWidget()) - subWindow = qobject_cast(parent); - const bool restore = subWindow && subWindow->isHidden(); plot->show(); - if(subWindow) { - // 敏感性子窗口标题使用数值模块译文,与历史图、直方图保持一致。 - subWindow->setWindowTitle(tr("Sensitivity loglog plot")); - subWindow->show(); - if(created || restore) { - ZxMdiArea* area = qobject_cast(subWindow->mdiArea()); - fitting->layoutSubWnds(area ? area->getLayoutMode() : WLM_Cell); - } - } - if(sender() == manager) fitting->setModified(true); + window->setProperty("nmResultDirty", false); + if(window->isMinimized()) window->showNormal(); + else window->show(); + window->raise(); + window->activateWindow(); } void nmSubWndMain::updateSensitiveHistoryPlot() { - // 复用框架的上下压力/流量控件,作为同一分析页面中的独立 MDI 子窗口。 + // 复用框架的上下压力/流量控件,在本分析的独立对话框展示。 iSubWndFitting* fitting = m_pResultRefreshFitting.data(); nmDataAnalyzeManager* manager = m_pResultRefreshDataManager.data(); - if(!fitting || !fitting->m_pMdiArea || !manager || !manager->getSensitiveData()) return; - ZxMdiArea* area = fitting->m_pMdiArea; - QMdiSubWindow* window = area->findChild("nmSensitivityHistory"); + if(!fitting || !manager || !manager->getSensitiveData()) return; + QDialog* window = fitting->findChild("nmSensitivityHistory"); const QSharedPointer batch = manager->getSensitiveData()->getResults(); if(batch.isNull()) { - // 新模型丢弃旧批次时一并销毁窗口,曲线和撤销记录不再残留。 - if(window) { - area->removeSubWindow(window); - delete window; - } + // 新模型丢弃旧批次时清空并隐藏窗口,曲线和撤销记录不再残留。 + resetResultDialog(window); return; } const bool created = window == nullptr; if(created) { - // PF 继承对话框,用普通页面承载,关闭子窗口时不进入其对话框关闭流程。 - QWidget* page = new QWidget; - QVBoxLayout* layout = new QVBoxLayout(page); - layout->setContentsMargins(0, 0, 0, 0); + // PF 作为对话框内的控件使用,保留框架的上下曲线布局。 + window = createResultDialog("nmSensitivityHistory", tr("Sensitivity history plot")); + QWidget* page = window; + QVBoxLayout* layout = qobject_cast(window->layout()); iGuiPlotPF* history = new iGuiPlotPF(s_Tag_HIST_PF, true, true, page); history->setWindowFlags(Qt::Widget); history->initUI(tr("Sensitivity history plot")); history->setTableHelperVisible(false); layout->addWidget(history); - window = area->addSubWindow(page); - window->setObjectName("nmSensitivityHistory"); - window->setWindowTitle(tr("Sensitivity history plot")); - window->setAttribute(Qt::WA_DeleteOnClose, false); } - installSensitiveShow(window->widget()); + installSensitiveShow(window); iGuiPlotPF* history = window->findChild(); QVector curves; // 基准压力、实测压力和流量均取成功求解快照,未求解的参数或制度编辑不参与绘图。 @@ -2408,13 +2422,14 @@ void nmSubWndMain::updateSensitiveHistoryPlot() plot->setReadOnly(true); plot->freshAxisScales(true, true); } - const bool restore = window->isHidden(); history->show(); - window->widget()->show(); - window->show(); + window->setProperty("nmResultDirty", false); + if(window->isMinimized()) window->showNormal(); + else window->show(); // 历史图只显示曲线,隐藏框架默认的空数据表侧栏。 history->m_pTableHelper->hide(); - if(created || restore) area->relayoutSubWnds(); + window->raise(); + window->activateWindow(); } void nmSubWndMain::installSensitiveShow(QWidget* host) @@ -2455,7 +2470,9 @@ void nmSubWndMain::onSensitiveShowClicked() // 发布新批次或清除旧模型后关闭旧表格,不能再操作上一批曲线。 connect(manager, SIGNAL(sigSensitiveResultsChanged()), dialog, SLOT(reject())); } - dialog->show(); + dialog->setResults(batch); + if(dialog->isMinimized()) dialog->showNormal(); + else dialog->show(); dialog->raise(); dialog->activateWindow(); } @@ -2464,23 +2481,19 @@ void nmSubWndMain::updateSensitiveHistogramPlot() { iSubWndFitting* fitting = m_pResultRefreshFitting.data(); nmDataAnalyzeManager* manager = m_pResultRefreshDataManager.data(); - if(!fitting || !fitting->m_pMdiArea || !manager || !manager->getSensitiveData()) return; - ZxMdiArea* area = fitting->m_pMdiArea; - QMdiSubWindow* window = area->findChild("nmSensitivityHistogram"); + if(!fitting || !manager || !manager->getSensitiveData()) return; + QDialog* window = fitting->findChild("nmSensitivityHistogram"); const QSharedPointer batch = manager->getSensitiveData()->getResults(); if(batch.isNull() || batch->m_calcType != nmDataSensitive::CALC_MONTE_CARLO) { // 新模型或确定性批次不保留上一批 Monte-Carlo 的统计图。 - if(window) { - area->removeSubWindow(window); - delete window; - } + resetResultDialog(window); return; } const bool created = window == nullptr; if(created) { - QWidget* page = new QWidget; - QVBoxLayout* layout = new QVBoxLayout(page); - layout->setContentsMargins(0, 0, 0, 0); + window = createResultDialog("nmSensitivityHistogram", tr("Sensitivity histogram plot")); + QWidget* page = window; + QVBoxLayout* layout = qobject_cast(window->layout()); QHBoxLayout* options = new QHBoxLayout; QPushButton* scatter = new QPushButton(tr("Scatter plot"), page); scatter->setObjectName("nmScatterButton"); @@ -2502,14 +2515,10 @@ void nmSubWndMain::updateSensitiveHistogramPlot() plot->getAxisOf(i)->setVisible(true); } layout->addWidget(plot); - window = area->addSubWindow(page); - window->setObjectName("nmSensitivityHistogram"); - window->setWindowTitle(tr("Sensitivity histogram plot")); - window->setAttribute(Qt::WA_DeleteOnClose, false); connect(scatter, SIGNAL(clicked()), this, SLOT(onSensitiveScatter())); connect(settings, SIGNAL(clicked()), this, SLOT(onSensitiveHistogramOptions())); } - iGuiPlot* plot = window->widget()->findChild(); + iGuiPlot* plot = window->findChild(); const int binCount = batch->m_nHistogramBins; // 拟合参数与误差共用分箱绘制,轴名称和单位随本批选择同步切换。 const int variable = batch->m_nHistogramVariable; @@ -2544,6 +2553,7 @@ void nmSubWndMain::updateSensitiveHistogramPlot() const int index = qMin(binCount - 1, int((values[i] - minimum) / width)); ++counts[index]; } + clearResultCurveDataTables(plot); for(int i = plot->m_pPlot->getObjCount() - 1; i >= 0; --i) if(qobject_cast(plot->m_pPlot->getObjByIndex(i))) plot->m_pPlot->removeObjByIndex(i); plot->clearUndoStack(); @@ -2600,11 +2610,12 @@ void nmSubWndMain::updateSensitiveHistogramPlot() plot->setAxisScaleX(minimum, maximum, ticksX); plot->setAxisScaleY(0.0, top, ticksY); plot->setAxisScaleY2(0.0, 110.0, ticksY2); - const bool restore = window->isHidden(); plot->show(); - window->widget()->show(); - window->show(); - if(created || restore) area->relayoutSubWnds(); + window->setProperty("nmResultDirty", false); + if(window->isMinimized()) window->showNormal(); + else window->show(); + window->raise(); + window->activateWindow(); } void nmSubWndMain::onSensitiveHistogramOptions() @@ -2612,17 +2623,19 @@ void nmSubWndMain::onSensitiveHistogramOptions() // 设置窗口复用当前批次,分箱数在 Apply 或 OK 后才应用到直方图。 iSubWndFitting* fitting = m_pResultRefreshFitting.data(); nmDataAnalyzeManager* manager = m_pResultRefreshDataManager.data(); - if(!fitting || !fitting->m_pMdiArea || !manager || !manager->getSensitiveData()) return; - QMdiSubWindow* window = fitting->m_pMdiArea->findChild("nmSensitivityHistogram"); + if(!fitting || !manager || !manager->getSensitiveData()) return; + QDialog* window = fitting->findChild("nmSensitivityHistogram"); const QSharedPointer batch = manager->getSensitiveData()->getResults(); if(!window || batch.isNull()) return; nmWxSensitivityHistogramOptions* dialog = window->findChild(); if(!dialog) { - dialog = new nmWxSensitivityHistogramOptions(batch, batch->m_nHistogramBins, window->widget()); + dialog = new nmWxSensitivityHistogramOptions(batch, batch->m_nHistogramBins, window); connect(dialog, SIGNAL(settingsChanged(int,int)), this, SLOT(onSensitiveHistogramSettingsChanged(int,int))); connect(manager, SIGNAL(sigSensitiveResultsChanged()), dialog, SLOT(reject())); } - dialog->show(); + dialog->setResults(batch); + if(dialog->isMinimized()) dialog->showNormal(); + else dialog->show(); dialog->raise(); dialog->activateWindow(); } @@ -2637,8 +2650,8 @@ void nmSubWndMain::onSensitiveHistogramSettingsChanged(int bins, int variable) batch->m_nHistogramVariable = variable; batch->m_nHistogramBins = bins; iSubWndFitting* fitting = m_pResultRefreshFitting.data(); - if(!fitting || !fitting->m_pMdiArea) return; - QMdiSubWindow* window = fitting->m_pMdiArea->findChild("nmSensitivityHistogram"); + if(!fitting) return; + QDialog* window = fitting->findChild("nmSensitivityHistogram"); if(!window) return; fitting->setModified(true); updateSensitiveHistogramPlot(); @@ -2661,30 +2674,32 @@ void nmSubWndMain::onSensitiveScatter() // 与 Show 一样打开独立弹窗,重复点击时激活已有窗口。 iSubWndFitting* fitting = m_pResultRefreshFitting.data(); nmDataAnalyzeManager* manager = m_pResultRefreshDataManager.data(); - if(!fitting || !fitting->m_pMdiArea || !manager || !manager->getSensitiveData()) return; + if(!fitting || !manager || !manager->getSensitiveData()) return; const QSharedPointer batch = manager->getSensitiveData()->getResults(); if(batch.isNull() || batch->m_calcType != nmDataSensitive::CALC_MONTE_CARLO) return; - QMdiSubWindow* window = fitting->m_pMdiArea->findChild("nmSensitivityHistogram"); + QDialog* window = fitting->findChild("nmSensitivityHistogram"); if(!window) return; nmWxSensitivityScatter* dialog = window->findChild(); + double baseError = -1.0; + const QSharedPointer snapshot = manager->getPebiResultSnapshot(); + for(int i = 0; !snapshot.isNull() && i < snapshot->getWellCount(); ++i) { + const nmPebiResultWellSnapshot* well = snapshot->getWellAt(i); + if(well->m_sWellCode != batch->m_sWellCode) continue; + baseError = nmCalculationDllPebiSolverTask::calculatePressureRmse( + well->m_oCurves.m_vecHistoryPressure, well->m_oCurves.m_vecResultPressure); + break; + } if(!dialog) { - double baseError = -1.0; - const QSharedPointer snapshot = manager->getPebiResultSnapshot(); - for(int i = 0; !snapshot.isNull() && i < snapshot->getWellCount(); ++i) { - const nmPebiResultWellSnapshot* well = snapshot->getWellAt(i); - if(well->m_sWellCode != batch->m_sWellCode) continue; - baseError = nmCalculationDllPebiSolverTask::calculatePressureRmse( - well->m_oCurves.m_vecHistoryPressure, well->m_oCurves.m_vecResultPressure); - break; - } - dialog = new nmWxSensitivityScatter(batch, baseError, window->widget()); + dialog = new nmWxSensitivityScatter(batch, baseError, window); connect(dialog, SIGNAL(filterChanged()), this, SLOT(onSensitiveFilterChanged())); // 构造时已应用初始阈值,连接完成后补一次结果面板同步。 onSensitiveFilterChanged(); // 新结果或新模型生成后关闭弹窗,避免保留旧批次的点和阈值。 connect(manager, SIGNAL(sigSensitiveResultsChanged()), dialog, SLOT(reject())); } - dialog->show(); + dialog->setResults(batch, baseError); + if(dialog->isMinimized()) dialog->showNormal(); + else dialog->show(); dialog->raise(); dialog->activateWindow(); } diff --git a/Src/nmNum/nmSubWnd/nmSubWndUtils.cpp b/Src/nmNum/nmSubWnd/nmSubWndUtils.cpp index faa7ce95..ae3c2ef6 100644 --- a/Src/nmNum/nmSubWnd/nmSubWndUtils.cpp +++ b/Src/nmNum/nmSubWnd/nmSubWndUtils.cpp @@ -485,18 +485,21 @@ void nmSubWndUtils::setupNumericalDockWidgets(nmDataAnalyzeManager* pDataManager pSubWndMain, SLOT(onForecastTaskReady(nmWxForecast*,nmCalculationDllPebiSolverTask*))); connect(pAnalWx, SIGNAL(sigSensitivityTaskReady(nmWxSensitive*,nmCalculationDllPebiSolverTask*)), pSubWndMain, SLOT(onSensitivityTaskReady(nmWxSensitive*,nmCalculationDllPebiSolverTask*))); + connect(pAnalWx, SIGNAL(sigShowForecastResult()), + pSubWndMain, SLOT(onShowForecastResult())); + connect(pAnalWx, SIGNAL(sigShowSensitivityResult(int)), + pSubWndMain, SLOT(onShowSensitiveResult(int))); connect(pAnalWx, SIGNAL(sigResultWellChanged(QString)), pSubWndMain, SLOT(onWellSelected(QString))); // 手工求解和自动拟合都发布同一种正式快照,统一复用主窗口结果刷新逻辑。 pSubWndMain->bindPebiResultRefreshContext(pDataManager, pSubWndFitting); - // 预测发布和失效统一由数据管理器通知,加载时也复用同一绘图入口。 + // 新计算结果自动展示;项目读取只恢复数据,由设置窗口按需打开结果图。 connect(pDataManager, SIGNAL(sigForecastDataChanged()), pSubWndMain, SLOT(onForecastDataChanged()), Qt::UniqueConnection); connect(pDataManager, SIGNAL(sigForecastResultChanged()), pSubWndMain, SLOT(onShowForecastResult()), Qt::UniqueConnection); - connect(pDataManager, SIGNAL(sigPebiResultSnapshotChanged()), - pSubWndMain, SLOT(onShowForecastResult()), Qt::UniqueConnection); + connect(pDataManager, SIGNAL(sigSensitiveResultsChanged()), pSubWndMain, SLOT(onShowSensitiveResults()), static_cast(Qt::QueuedConnection | Qt::UniqueConnection)); @@ -508,10 +511,7 @@ void nmSubWndUtils::setupNumericalDockWidgets(nmDataAnalyzeManager* pDataManager pWxDockNm1->setWidget(pAnalWx); pWxDockNm2->setWidget(pParaWx); - // 成果加载和首次创建面板共用入口,有已保存的敏感性结果时恢复同一子窗口。 - if(pDataManager->getSensitiveData() && !pDataManager->getSensitiveData()->getResults().isNull()) - pSubWndMain->onShowSensitiveResults(); - pSubWndMain->onShowForecastResult(); + } bool nmSubWndUtils::fillNmDockWxs(iSubWnd* pSubWnd) diff --git a/Src/nmNum/nmSubWxs/nmParameterField.cpp b/Src/nmNum/nmSubWxs/nmParameterField.cpp index 30765f87..bc2a9693 100644 --- a/Src/nmNum/nmSubWxs/nmParameterField.cpp +++ b/Src/nmNum/nmSubWxs/nmParameterField.cpp @@ -221,7 +221,7 @@ void resolveParameterUnitSpelling(iParameter* pParameter) } // 参数XML和单位XML可能使用不同排版写法,绑定前切到当前单位表可识别的单位名。 - QString sResolvedUnit = resolveAvailableUnitSpelling(pParameter->m_sUnit); + QString sResolvedUnit = nmParameterField::resolveUnitSpelling(pParameter->m_sUnit); if (sResolvedUnit != pParameter->m_sUnit) { pParameter->m_sUnit = sResolvedUnit; @@ -341,6 +341,12 @@ int nmParameterField::editorMinimumWidth() return 140; } +QString nmParameterField::resolveUnitSpelling(const QString& sUnit) +{ + // 参数编辑与采样界面共用名称解析,避免普通指数与上标写法匹配到不同单位。 + return resolveAvailableUnitSpelling(sUnit); +} + int nmParameterField::unitMinimumWidth() { return 86; diff --git a/Src/nmNum/nmSubWxs/nmWxAutomaticFitting.cpp b/Src/nmNum/nmSubWxs/nmWxAutomaticFitting.cpp index 27c726da..f8fd803d 100644 --- a/Src/nmNum/nmSubWxs/nmWxAutomaticFitting.cpp +++ b/Src/nmNum/nmSubWxs/nmWxAutomaticFitting.cpp @@ -329,6 +329,26 @@ nmWxAutomaticFitting::nmWxAutomaticFitting(QWidget *parent, nmSensitivityFitSett DEBUG_UI("AutoFitting Constructor completed"); } +void nmWxAutomaticFitting::reloadSensitivitySettings(const QStringList& sampledParameters) +{ + // 敏感性设置复用原对话框,每次打开恢复已确认配置和本次禁用的采样参数。 + m_sampledParameters = sampledParameters; + nmDataAnalyzeManager* manager = nmDataAnalyzeManager::getCurrentInstance(); + reservoirData = manager->getReservoirDataCopy(); + automaticFittingData = m_sensitivitySettings->confirmed + ? m_sensitivitySettings->parameters : manager->getAutomaticFittingDataCopy(); + if(!m_sensitivitySettings->confirmed) automaticFittingData.getModelParameters().clear(); + nmDataWellBase* well = manager->findWellByCode(manager->getPrimaryWellCode()); + m_targetWellName = well ? well->getWellName() : QString(); + m_targetWellCode = well ? well->getWellCode() : QString(); + m_updatingParameterRanges = true; + initializeModelParameters(); + m_iterationEdit->setText(QString::number(automaticFittingData.getIterationCount().getValue().toInt())); + m_errorLimitEdit->setText(QString::number(automaticFittingData.getErrorTolerance().getValue().toDouble())); + onAlgorithmChanged(1); + m_updatingParameterRanges = false; +} + QSize nmWxAutomaticFitting::sizeHint() const { // 与改版前设置窗口保持相同推荐尺寸,仍允许手动放大。 diff --git a/Src/nmNum/nmSubWxs/nmWxAutomaticFittingStart.cpp b/Src/nmNum/nmSubWxs/nmWxAutomaticFittingStart.cpp index be59f969..3624112c 100644 --- a/Src/nmNum/nmSubWxs/nmWxAutomaticFittingStart.cpp +++ b/Src/nmNum/nmSubWxs/nmWxAutomaticFittingStart.cpp @@ -181,7 +181,8 @@ void nmAutomaticFittingCurveChart::paintEvent(QPaintEvent* event) QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing); - painter.fillRect(rect(), QColor(240, 240, 240)); + // 图表内外统一使用白色背景。 + painter.fillRect(rect(), Qt::white); const int marginLeft = 62; const int marginTop = 18; @@ -191,7 +192,7 @@ void nmAutomaticFittingCurveChart::paintEvent(QPaintEvent* event) qMax(10, width() - marginLeft - marginRight), qMax(10, height() - marginTop - marginBottom)); - painter.fillRect(m_chartRect, QColor(252, 252, 252)); + painter.fillRect(m_chartRect, Qt::white); drawGrid(painter); drawAxes(painter); drawCurveLine(painter, m_bestPressure, QColor(250, 74, 74)); diff --git a/Src/nmNum/nmSubWxs/nmWxForecast.cpp b/Src/nmNum/nmSubWxs/nmWxForecast.cpp index b6501a9e..5ee21081 100644 --- a/Src/nmNum/nmSubWxs/nmWxForecast.cpp +++ b/Src/nmNum/nmSubWxs/nmWxForecast.cpp @@ -4,13 +4,14 @@ #include #include #include +#include #include #include -#include #include #include "nmCalculationDllPebiSolverTask.h" #include "nmGUIComponentLineEdit.h" #include "nmPebiResultSnapshot.h" +#include "ZxBaseUtil.h" nmWxForecast::nmWxForecast(QWidget *parent, nmDataAnalyzeManager* manager) : iDlgBase(parent) @@ -35,7 +36,8 @@ nmWxForecast::nmWxForecast(QWidget *parent, nmDataAnalyzeManager* manager) , m_extEmpty(nullptr) { setWindowTitle(tr("Forecast")); - setFixedSize(520, 560); + resize(560, 560); + setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); // 关闭时只隐藏,所属设计面板复用同一个输入窗口。 setAttribute(Qt::WA_DeleteOnClose, false); @@ -55,24 +57,21 @@ nmWxForecast::nmWxForecast(QWidget *parent, nmDataAnalyzeManager* manager) // 根据加载的数据更新界面 updateParametersForOption(); - // 初始化完成后再同步编辑,避免加载项目时被标记为修改。 - connect(m_rateTableWidget, SIGNAL(cellChanged(int,int)), this, SLOT(saveDataToManager())); - connect(m_rDurationUnitCombo, SIGNAL(currentIndexChanged(QString)), this, SLOT(saveDataToManager())); - connect(m_rRateUnitCombo, SIGNAL(currentIndexChanged(QString)), this, SLOT(saveDataToManager())); - const QList edits = m_initialPressureComponent->findChildren(); - foreach(QLineEdit* edit, edits) - connect(edit, SIGNAL(textEdited(QString)), this, SLOT(saveDataToManager())); + // 编辑内容保留在窗口中,点击生成后再提交到数据中心。 const QList units = m_initialPressureComponent->findChildren(); foreach(QComboBox* unit, units) { const int index = unit->findData(m_forecastData.getMultipleRatesData().pressureUnit); if(index >= 0) unit->setCurrentIndex(index); - connect(unit, SIGNAL(currentIndexChanged(QString)), this, SLOT(saveDataToManager())); } if(m_manager) { connect(m_manager, SIGNAL(sigPebiResultSnapshotChanged()), this, SLOT(onModelChanged())); + connect(m_manager, SIGNAL(sigPebiResultSnapshotChanged()), this, SLOT(reloadInputData())); connect(m_manager, SIGNAL(sigPebiResultStateChanged()), this, SLOT(onModelChanged())); + connect(m_manager, SIGNAL(sigForecastResultChanged()), this, SLOT(updateResultButton())); + connect(m_manager, SIGNAL(sigPebiResultSnapshotChanged()), this, SLOT(updateResultButton())); connect(m_manager, SIGNAL(destroyed()), this, SLOT(close())); } + updateResultButton(); } nmWxForecast::~nmWxForecast() @@ -109,9 +108,17 @@ void nmWxForecast::loadDataFromManager() m_multipleRatesRadio->blockSignals(false); } +void nmWxForecast::reloadInputData() +{ + // 保留输入窗口,模型或项目读取通知后同步数据中心配置。 + if(m_calculationRunning) return; + loadDataFromManager(); + updateParametersForOption(); +} + void nmWxForecast::saveDataToManager() { - // 先从界面更新数据 + // 生成前统一收集输入,编辑和关闭窗口时不提交到数据中心。 updateDataFromUI(); const QList units = m_initialPressureComponent->findChildren(); @@ -128,11 +135,16 @@ void nmWxForecast::saveDataToManager() void nmWxForecast::setupUI() { + // 与储层参数窗口统一边距,表格随窗口大小扩展。 m_mainLayout = new QVBoxLayout(this); + m_mainLayout->setContentsMargins(12, 10, 12, 0); + m_mainLayout->setSpacing(8); // ========== Forecast options ========== m_forecastOptionsGroup = new QGroupBox(tr("Forecast options"), this); m_forecastOptionsLayout = new QVBoxLayout(m_forecastOptionsGroup); + m_forecastOptionsLayout->setContentsMargins(10, 10, 10, 10); + m_forecastOptionsLayout->setSpacing(8); m_constantPressureRadio = new QRadioButton(tr("Constant pressure"), this); m_decliningPressureRadio = new QRadioButton(tr("Declining pressure (ramp)"), this); @@ -154,10 +166,14 @@ void nmWxForecast::setupUI() m_usePastHistoryCheck->setEnabled(false); m_surfacePressuresCheck->setEnabled(false); - m_forecastOptionsLayout->addWidget(m_constantPressureRadio); - m_forecastOptionsLayout->addWidget(m_decliningPressureRadio); - m_forecastOptionsLayout->addWidget(m_multiplePressuresRadio); - m_forecastOptionsLayout->addWidget(m_multipleRatesRadio); + QGridLayout* optionsLayout = new QGridLayout(); + optionsLayout->setHorizontalSpacing(16); + optionsLayout->setVerticalSpacing(8); + optionsLayout->addWidget(m_constantPressureRadio, 0, 0); + optionsLayout->addWidget(m_decliningPressureRadio, 0, 1); + optionsLayout->addWidget(m_multiplePressuresRadio, 1, 0); + optionsLayout->addWidget(m_multipleRatesRadio, 1, 1); + m_forecastOptionsLayout->addLayout(optionsLayout); QHBoxLayout *checkBoxLayout = new QHBoxLayout(); checkBoxLayout->addWidget(m_usePastHistoryCheck); @@ -168,11 +184,12 @@ void nmWxForecast::setupUI() // ========== Parameters ========== m_parametersGroup = new QGroupBox(tr("Parameters"), this); QVBoxLayout *parametersOuterLayout = new QVBoxLayout(m_parametersGroup); - parametersOuterLayout->setContentsMargins(6, 6, 6, 6); + parametersOuterLayout->setContentsMargins(10, 10, 10, 10); // 基础区 QWidget *baseWidget = new QWidget(this); m_parametersLayout = new QGridLayout(baseWidget); + m_parametersLayout->setContentsMargins(0, 0, 0, 0); m_parametersLayout->setHorizontalSpacing(8); m_parametersLayout->setVerticalSpacing(8); m_parametersLayout->setColumnStretch(0, 0); // 复选框列 @@ -180,11 +197,6 @@ void nmWxForecast::setupUI() int row = 0; - // 1. 创建一个“占位符” (strut),用于永久撑开第0列 - QWidget* column0Strut = new QWidget(this); - // 2. 将占位符添加到 (row 0, col 0) - m_parametersLayout->addWidget(column0Strut, row, 0); - // (row 0) Initial pressure ConstantPressure& constantPressureData = m_forecastData.getConstantPressureData(); m_initialPressureComponent = new nmGUIComponentLineEdit( @@ -192,7 +204,23 @@ void nmWxForecast::setupUI() true, this ); - m_parametersLayout->addWidget(m_initialPressureComponent, row, 1); + // 标签按内容占宽,数值和单位按储层参数页的比例铺满剩余空间。 + QLabel* pressureLabel = m_initialPressureComponent->findChild(); + // 先解除通用控件的 200 像素标签限制,再由布局按实际文字宽度分配。 + pressureLabel->setMinimumWidth(0); + pressureLabel->setMaximumWidth(QWIDGETSIZE_MAX); + pressureLabel->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Fixed); + QLineEdit* pressureEdit = m_initialPressureComponent->findChild(); + QComboBox* pressureUnit = m_initialPressureComponent->findChild(); + pressureEdit->setMinimumWidth(140); + pressureEdit->setMaximumWidth(QWIDGETSIZE_MAX); + pressureUnit->setMinimumWidth(86); + pressureUnit->setMaximumWidth(QWIDGETSIZE_MAX); + QHBoxLayout* pressureLayout = static_cast(m_initialPressureComponent->layout()); + delete pressureLayout->takeAt(1); // 移除标签后的弹性留白。 + pressureLayout->setStretchFactor(pressureEdit, 8); + pressureLayout->setStretchFactor(pressureUnit, 5); + m_parametersLayout->addWidget(m_initialPressureComponent, row, 0, 1, 2); row++; // (row 1) Abandonment rate @@ -227,10 +255,6 @@ void nmWxForecast::setupUI() m_parametersLayout->addWidget(m_forecastDurationComponent, row, 1); row++; - // 设置占位符的固定宽度,使其等于复选框的宽度 - int chkBoxWidth = m_abandonmentRateCheck->minimumSizeHint().width(); - column0Strut->setFixedWidth(chkBoxWidth); - // (row 4) Producing pressure m_producingPressureComponent = new nmGUIComponentLineEdit(&m_forecastData.getConstantPressureData().getProducingPressure(), true, this); m_parametersLayout->addWidget(m_producingPressureComponent, row, 1); @@ -261,34 +285,42 @@ void nmWxForecast::setupUI() m_extStackedWidget->addWidget(m_extMultiP); // 页面 2 m_extStackedWidget->addWidget(m_extMultiR); // 页面 3 - // --- 4. 将 QStackedWidget 添加到布局的固定位置 (row 5) --- - m_parametersLayout->addWidget(m_extStackedWidget, row, 1); - row++; // row 变为 6 - parametersOuterLayout->addWidget(baseWidget); - //parametersOuterLayout->addWidget(m_extStackedWidget); + + // 制度表格单独分组,占用参数区下方的可用空间。 + QGroupBox* scheduleGroup = new QGroupBox(tr("Multiple rates"), this); + QVBoxLayout* scheduleLayout = new QVBoxLayout(scheduleGroup); + scheduleLayout->setContentsMargins(10, 10, 10, 10); + scheduleLayout->addWidget(m_extStackedWidget); // ========== Buttons ========== m_buttonLayout = new QHBoxLayout(); + m_buttonLayout->setContentsMargins(4, 5, 4, 5); + m_buttonLayout->setSpacing(8); m_loadDataButton = new QPushButton(tr("Load data"), this); m_generateButton = new QPushButton(tr("Generate"), this); + // 只有一张预测结果图,直接打开已有结果,不重新求解。 + m_resultPlotButton = new QPushButton(tr("Result plots"), this); + m_resultPlotButton->setObjectName("nmForecastResultPlots"); m_cancelButton = new QPushButton(tr("Cancel"), this); m_loadDataButton->setEnabled(false); + m_generateButton->setIcon(zxLoadIcon("OK")); + m_cancelButton->setIcon(zxLoadIcon("Cancel")); m_buttonLayout->addWidget(m_loadDataButton); m_buttonLayout->addStretch(); + m_buttonLayout->addWidget(m_resultPlotButton); m_buttonLayout->addWidget(m_generateButton); m_buttonLayout->addWidget(m_cancelButton); // ========== Main ========== m_mainLayout->addWidget(m_forecastOptionsGroup); m_mainLayout->addWidget(m_parametersGroup); - m_mainLayout->addStretch(); + m_mainLayout->addWidget(scheduleGroup, 1); m_mainLayout->addLayout(m_buttonLayout); // 收集所有组件 QList allComponents; - allComponents.append(m_initialPressureComponent); allComponents.append(m_abandonmentRateComponent); allComponents.append(m_maximumRateComponent); allComponents.append(m_forecastDurationComponent); @@ -524,6 +556,7 @@ void nmWxForecast::setupConnections() // Buttons connect(m_loadDataButton, SIGNAL(clicked()), this, SLOT(onLoadDataClicked())); connect(m_generateButton, SIGNAL(clicked()), this, SLOT(onGenerateClicked())); + connect(m_resultPlotButton, SIGNAL(clicked()), this, SIGNAL(sigShowForecastResult())); connect(m_cancelButton, SIGNAL(clicked()), this, SLOT(onCancelClicked())); // Pressure Table @@ -634,6 +667,10 @@ void nmWxForecast::updateParametersForOption() const nmDataForecast::ForecastOption option = m_forecastData.getForecastOption(); + // 隐藏不适用的整行,避免多段产量模式留下空白占位。 + m_abandonmentStack->setVisible(option != nmDataForecast::MultipleRatesOption); + m_maximumStack->setVisible(option != nmDataForecast::MultipleRatesOption); + // 默认显示所有基本组件 if (m_abandonmentRateCheck) m_abandonmentRateCheck->setVisible(true); if (m_abandonmentStack) m_abandonmentStack->setCurrentIndex(0); @@ -1182,6 +1219,18 @@ void nmWxForecast::onForecastFinished() m_forecastData.setResult(QSharedPointer()); } +void nmWxForecast::updateResultButton() +{ + // 与结果绘图入口保持相同的有效性条件,读取项目后即可查看已保存的结果。 + const QSharedPointer result = m_manager && m_manager->getForecastData() + ? m_manager->getForecastData()->getResult() : QSharedPointer(); + const QSharedPointer snapshot = m_manager + ? m_manager->getPebiResultSnapshot() : QSharedPointer(); + m_resultPlotButton->setEnabled(!result.isNull() && !snapshot.isNull() && + result->snapshotId == snapshot->getSnapshotId() && + result->wellInstanceId == m_manager->getCurrentResultWellInstanceId()); +} + void nmWxForecast::onModelChanged() { // 模型或输入改变时停止本次计算;已显示的结果由所属主界面清理。 diff --git a/Src/nmNum/nmSubWxs/nmWxNumericalDesign.cpp b/Src/nmNum/nmSubWxs/nmWxNumericalDesign.cpp index 7c691aab..13f79352 100644 --- a/Src/nmNum/nmSubWxs/nmWxNumericalDesign.cpp +++ b/Src/nmNum/nmSubWxs/nmWxNumericalDesign.cpp @@ -200,9 +200,10 @@ nmWxNumericalDesign::nmWxNumericalDesign( m_pApplyUnconsolidationIconButton->setVisible(bDebugOptionsVisible); m_pUseDFNCheck->setVisible(bDebugOptionsVisible); m_pNumericalSettingsGroup->setVisible(bDebugOptionsVisible); - // 暂时隐藏预测和敏感性分析入口。 - m_pForecastBtn->setVisible(false); - m_pSensitiveBtn->setVisible(false); + // 预测配置界面在 Debug 和 Release 下均显示。 + m_pForecastBtn->setVisible(true); + // 敏感性分析配置界面在 Debug 和 Release 下均显示。 + m_pSensitiveBtn->setVisible(true); } nmWxNumericalDesign::~nmWxNumericalDesign() @@ -1450,6 +1451,8 @@ void nmWxNumericalDesign::onForecastClicked() // 关闭和生成后均保留输入窗口,只在首次使用时创建并连接任务信号。 if(m_pForecastDialog.isNull()) { m_pForecastDialog = new nmWxForecast(this, m_pDataManager); + // 设置窗口只请求查看,绘图仍交给所属主窗口。 + connect(m_pForecastDialog, SIGNAL(sigShowForecastResult()), this, SIGNAL(sigShowForecastResult())); connect(m_pForecastDialog, SIGNAL(sigForecastTaskReady(nmWxForecast*,nmCalculationDllPebiSolverTask*)), this, SIGNAL(sigForecastTaskReady(nmWxForecast*,nmCalculationDllPebiSolverTask*))); } @@ -1476,11 +1479,17 @@ void nmWxNumericalDesign::onSensitiveClicked() // 没有模型时直接阻止进入,正常交互由按钮置灰表达,不再等生成分析时弹框。 updateSensitiveButtonEnabled(); if(!m_pSensitiveBtn->isEnabled()) return; - nmWxSensitive* dlg = new nmWxSensitive(this, m_pDataManager); - // 按数值生成按钮的现有路径,将任务请求转发给所属主窗口。 - connect(dlg, SIGNAL(sigSensitivityTaskReady(nmWxSensitive*,nmCalculationDllPebiSolverTask*)), - this, SIGNAL(sigSensitivityTaskReady(nmWxSensitive*,nmCalculationDllPebiSolverTask*))); - dlg->show(); + // 每个分析只创建一个输入窗口,关闭后隐藏,重新打开直接激活。 + if(m_pSensitiveDialog.isNull()) { + m_pSensitiveDialog = new nmWxSensitive(this, m_pDataManager); + connect(m_pSensitiveDialog, SIGNAL(sigShowSensitivityResult(int)), this, SIGNAL(sigShowSensitivityResult(int))); + connect(m_pSensitiveDialog, SIGNAL(sigSensitivityTaskReady(nmWxSensitive*,nmCalculationDllPebiSolverTask*)), + this, SIGNAL(sigSensitivityTaskReady(nmWxSensitive*,nmCalculationDllPebiSolverTask*))); + } + if(m_pSensitiveDialog->isMinimized()) m_pSensitiveDialog->showNormal(); + else m_pSensitiveDialog->show(); + m_pSensitiveDialog->raise(); + m_pSensitiveDialog->activateWindow(); } // 实现通知方法 diff --git a/Src/nmNum/nmSubWxs/nmWxSensitive.cpp b/Src/nmNum/nmSubWxs/nmWxSensitive.cpp index 02081152..da56298f 100644 --- a/Src/nmNum/nmSubWxs/nmWxSensitive.cpp +++ b/Src/nmNum/nmSubWxs/nmWxSensitive.cpp @@ -2,6 +2,9 @@ #include "nmDataAnalyzeManager.h" #include "nmWxAutomaticFitting.h" +#include "nmParameterField.h" +#include "ZxBaseUtil.h" +#include #include "nmDataSensitive.h" #include "nmDataReservoir.h" #include "nmDataWellBase.h" @@ -122,21 +125,33 @@ QString samplingBaseUnit(const QString& name) } bool convertSamplingValue(const QString& name, double value, - QString from, QString to, double& converted) -{ - // 优先复用项目单位组;旧配置的 psi 按绝对压力单位迁移。 - if (from == "psi") from = "psia"; - if (to == "psi") to = "psia"; + QString from, QString to, double& converted, bool difference = false) +{ + // 标准差是差值,单位换算只应用比例,不带入表压和绝压之间的偏移。 + if (difference) { + double zero = 0.0; + if (!convertSamplingValue(name, 0.0, from, to, zero) || + !convertSamplingValue(name, value, from, to, converted)) return false; + converted -= zero; + return qIsFinite(converted); + } + // 优先使用框架单位组中的原始名称,兼容下拉框内的全部单位。 if (from == "dimensionless") from.clear(); if (to == "dimensionless") to.clear(); if (from == to || (from.isEmpty() && to.isEmpty())) { converted = value; return qIsFinite(converted); } + // 与井参数编辑共用名称解析,使 m^3/MPa 等旧写法也能参与框架换算。 + from = nmParameterField::resolveUnitSpelling(from); + to = nmParameterField::resolveUnitSpelling(to); iUnitGroup* group = iUnitHelper::getUnitGroupByUnit(from); int digit = 0; if (group && group->indexOf(to) >= 0 && group->convert(from, value, to, converted, digit)) return qIsFinite(converted); + // 旧配置未被框架识别时,沿用业务层的绝对压力单位换算。 + if (from == "psi") from = "psia"; + if (to == "psi") to = "psia"; if (name == "h") converted = nmDataAttribute::convertLengthUnit(value, from, to); else if (name == "Pi") converted = nmDataAttribute::convertPressureUnit(value, from, to); else if (name == "k") converted = nmDataAttribute::convertPermeabilityUnit(value, from, to); @@ -227,6 +242,18 @@ public: highlightRun(-1); } + QSharedPointer results() const { return m_results; } + + void setResults(const QSharedPointer& results) + { + // 重置行数与列数,旧批次的选择和高亮不能带到新结果。 + highlightRun(-1); + beginResetModel(); + m_pendingVisibility.clear(); + m_results = results; + endResetModel(); + } + QList runCurves(int row) const { // 双对数图的一组包含压力与导数,历史压力图只包含压力。 @@ -257,7 +284,7 @@ public: int columnCount(const QModelIndex& parent = QModelIndex()) const override { - return parent.isValid() ? 0 : 3 + (m_statistics ? m_results->m_fitParameters.size() : 0); + return parent.isValid() ? 0 : 3 + (m_statistics && !m_results.isNull() ? m_results->m_fitParameters.size() : 0); } QVariant headerData(int section, Qt::Orientation orientation, int role) const override @@ -278,7 +305,7 @@ public: } if(role != Qt::DisplayRole) return QVariant(); if(m_statistics) { - if(section >= 3 && section - 3 < m_results->m_fitParameters.size()) { + if(!m_results.isNull() && section >= 3 && section - 3 < m_results->m_fitParameters.size()) { const nmDataAttribute& parameter = m_results->m_fitParameters[section - 3]; return parameter.getName() + (parameter.getUnit().isEmpty() ? QString() : " [" + parameter.getUnit() + "]"); @@ -474,7 +501,7 @@ nmWxSensitivityShow::nmWxSensitivityShow( : iDlgBase(parent) { // 沿用原 Results 的白色表格及按钮布局,勾选在 Apply 或 OK 后生效。 - setAttribute(Qt::WA_DeleteOnClose); + setAttribute(Qt::WA_DeleteOnClose, false); setObjectName("nmSensitivityShowDialog"); resize(700, 380); QVBoxLayout* layout = new QVBoxLayout(this); @@ -522,10 +549,20 @@ nmWxSensitivityShow::nmWxSensitivityShow( void nmWxSensitivityShow::done(int result) { // 确认、取消及关闭都结束临时高亮,不改变已应用的显示选择。 - m_model->highlightRun(-1); + setResults(m_model->results()); iDlgBase::done(result); } +void nmWxSensitivityShow::setResults(const QSharedPointer& results) +{ + // 保留窗口和模型对象,重新打开时取消未应用的勾选和临时高亮。 + m_highlight->blockSignals(true); + m_highlight->setChecked(false); + m_highlight->blockSignals(false); + m_model->setResults(results); + updateHighlight(); +} + void nmWxSensitivityShow::onApply() { // 应用选择,保留窗口以便继续调整。 @@ -559,7 +596,7 @@ nmWxSensitivityHistogramOptions::nmWxSensitivityHistogramOptions( : iDlgBase(parent) { // 复用运行表格;第四种在误差后追加拟合参数,选择变量后按原有 Apply/OK 流程生效。 - setAttribute(Qt::WA_DeleteOnClose); + setAttribute(Qt::WA_DeleteOnClose, false); setObjectName("nmHistogramOptions"); setWindowTitle(tr("Histogram options")); resize(720, 400); @@ -579,7 +616,7 @@ nmWxSensitivityHistogramOptions::nmWxSensitivityHistogramOptions( m_variable->setCurrentIndex(m_variable->findData(results->m_nHistogramVariable)); options->addWidget(m_variable); layout->addLayout(options); - QTableView* table = new QTableView(this); + QTableView* table = m_table = new QTableView(this); table->setStyleSheet("QTableView { background-color: white; }"); table->setModel(new SensitivityResultsModel(results, nullptr, table, true)); table->setSelectionBehavior(QAbstractItemView::SelectRows); @@ -605,6 +642,22 @@ nmWxSensitivityHistogramOptions::nmWxSensitivityHistogramOptions( connect(cancel, SIGNAL(clicked()), this, SLOT(reject())); } +void nmWxSensitivityHistogramOptions::setResults(const QSharedPointer& results) +{ + // 复用表格模型,同时恢复当前批次已应用的分箱和统计变量。 + static_cast(m_table->model())->setResults(results); + m_variable->clear(); + m_variable->addItem(tr("Goodness of fit"), -1); + if(!results.isNull()) { + for(int i = 0; i < results->m_fitParameters.size(); ++i) + m_variable->addItem(results->m_fitParameters[i].getName(), i); + m_variable->setCurrentIndex(m_variable->findData(results->m_nHistogramVariable)); + m_bins->setValue(results->m_nHistogramBins); + } + for(int i = 2; i < m_table->model()->columnCount(); ++i) + m_table->horizontalHeader()->setResizeMode(i, QHeaderView::ResizeToContents); +} + void nmWxSensitivityHistogramOptions::onApply() { // 分箱数与横轴变量一起提交,取消不会撤销已经应用的设置。 @@ -625,7 +678,7 @@ nmWxSensitivityScatter::nmWxSensitivityScatter( { // 散点与基准均来自同一批次快照,不读取后来编辑的模型参数。 setObjectName("nmSensitivityScatterPlot"); - setAttribute(Qt::WA_DeleteOnClose); + setAttribute(Qt::WA_DeleteOnClose, false); setWindowTitle(tr("Scatter plot")); resize(850, 550); QVBoxLayout* layout = new QVBoxLayout(this); @@ -675,6 +728,42 @@ nmWxSensitivityScatter::nmWxSensitivityScatter( updateParameter(); } +void nmWxSensitivityScatter::setResults(const QSharedPointer& results, double baseError) +{ + // 同一批次保留坐标选择,新批次先清空旧图元与统计引用。 + if(m_results == results && !results.isNull()) return; + m_results = results; + m_baseError = baseError; + m_draggingThreshold = false; + m_points.clear(); + m_runRows.clear(); + for(int i = m_plot->m_pPlot->getObjCount() - 1; i >= 0; --i) + if(qobject_cast(m_plot->m_pPlot->getObjByIndex(i))) m_plot->m_pPlot->removeObjByIndex(i); + m_plot->clearUndoStack(); + m_plot->setCurveData(QVector()); + m_plot->runUpdate(); + m_parameter->blockSignals(true); + m_ordinate->blockSignals(true); + m_parameter->clear(); + m_ordinate->clear(); + m_ordinate->addItem(tr("Goodness of fit"), -1); + m_defaultThreshold = 0.0; + if(!results.isNull()) { + for(int i = 0; i < results->m_variables.size(); ++i) + if(results->m_variables[i].m_enabled) m_parameter->addItem(results->m_variables[i].displayName(), i); + for(int i = 0; i < results->m_fitParameters.size(); ++i) + m_ordinate->addItem(results->m_fitParameters[i].getName(), i); + for(size_t i = 0; i < results->m_runs.size(); ++i) + if(hasSensitivityError(results->m_runs[i])) m_defaultThreshold = qMax(m_defaultThreshold, results->m_runs[i].m_dPressureRmse); + if(qIsFinite(baseError) && baseError >= 0.0) m_defaultThreshold = baseError; + m_threshold = results->m_dFilterThreshold >= 0.0 ? results->m_dFilterThreshold : m_defaultThreshold; + } + m_parameter->blockSignals(false); + m_ordinate->blockSignals(false); + if(!results.isNull()) updateParameter(); + else m_legend->clear(); +} + void nmWxSensitivityScatter::updateParameter() { // 两轴切换都从本批结果重建坐标;拟合参数轴不使用误差阈值。 @@ -910,7 +999,7 @@ protected: { // 蓝线为累积概率,红色虚线为按峰值归一化的概率密度,与 Saphir 的显示一致。 QPainter painter(this); - painter.fillRect(rect(), palette().color(QPalette::Window)); + painter.fillRect(rect(), Qt::white); painter.setRenderHint(QPainter::Antialiasing); QVector x(201), cumulativeValues(201); const bool bounded = m_variable.m_distribution >= nmDataSensitive::VariableSampling::TRUNCATED_NORMAL; @@ -931,7 +1020,7 @@ protected: painter.drawText(rect(), Qt::AlignCenter, nmWxSensitive::tr("Invalid distribution parameters")); return; } - // 坐标外侧沿用窗口底色,绘图区留白,标题放在纵轴左侧。 + // 坐标内外统一使用白底,标题放在纵轴左侧。 const QRectF plot(76, 12, width() - 96, height() - 66); painter.fillRect(plot, Qt::white); const QRectF dataArea = plot.adjusted(12, 16, -12, -16); @@ -1098,6 +1187,8 @@ public: m_total(data.getTotalModelCount()), m_first(0), m_selected(0), m_visibleRows(1), m_updating(false), m_wheelDelta(0) { + // 预览只持有采样配置,不保留计算结果批次。 + m_data.setResults(QSharedPointer()); // 使用现有表格控件绘制表头、行选中和单元格,滚动条控制完整列表。 setFrameShape(QFrame::StyledPanel); setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); @@ -1339,8 +1430,11 @@ private: nmWxSensitive::nmWxSensitive(QWidget *parent, nmDataAnalyzeManager* manager) : iDlgBase(parent), m_selectedValueIndex(0), m_loading(true), m_pDataManager(manager ? manager : nmDataAnalyzeManager::getCurrentInstance()), + m_sourceData(m_pDataManager ? m_pDataManager->getSensitiveData() : nullptr), m_previewView(nullptr), m_pSensitivityTask(nullptr), m_calculationRunning(false) { + // 关闭只隐藏,由所属分析统一销毁,重新打开保留当前输入。 + setAttribute(Qt::WA_DeleteOnClose, false); // 显式绑定所属分析窗口,后续切换窗口不会改变配置保存目标。 if (m_pDataManager) m_sensitiveData = m_pDataManager->getSensitiveDataCopy(); refreshModelValues(); @@ -1375,7 +1469,11 @@ void nmWxSensitive::reject() { // Esc 与取消按钮使用相同的停止路径,保留已完成组供结束后查看。 if(m_calculationRunning) onCancelClicked(); - else iDlgBase::reject(); + else { + foreach(QDialog* dialog, findChildren()) + if(dialog->isWindow()) dialog->close(); + iDlgBase::reject(); + } } void nmWxSensitive::closeEvent(QCloseEvent* event) @@ -1443,7 +1541,9 @@ void nmWxSensitive::refreshModelValues() continue; } const QString baseUnit = samplingBaseUnit(name); - QString displayUnit = attribute->getUnit(); + // 已保存的采样显示单位独立于模型单位,重开及读取项目时继续沿用。 + QString displayUnit = !fresh && m_sensitiveData.usesBaseUnits() + ? variable.getModelValue().getUnit() : attribute->getUnit(); if (displayUnit == "dimensionless") displayUnit.clear(); double converted = 0.0; if (!convertSamplingValue(name, attribute->getValue().toDouble(), baseUnit, displayUnit, converted)) @@ -1527,12 +1627,35 @@ void nmWxSensitive::refreshModelValues() void nmWxSensitive::onModelResultChanged() { - // 通知后按当前模型刷新数值;未改变的参数保留用户范围。 + // 项目读取替换数据对象时重新加载;普通模型刷新保留当前未提交的采样输入。 + reloadInputData(); +} + +void nmWxSensitive::reloadInputData() +{ + if(m_calculationRunning) return; m_loading = true; + if(m_pDataManager && m_sourceData != m_pDataManager->getSensitiveData()) + m_sensitiveData = m_pDataManager->getSensitiveDataCopy(); + m_sourceData = m_pDataManager ? m_pDataManager->getSensitiveData() : nullptr; + foreach(QDialog* dialog, findChildren()) + if(dialog->isWindow()) dialog->close(); + delete m_previewView; + m_previewView = nullptr; refreshModelValues(); - loadDataToUI(true); + // 井列表可能改变,重建参数页,保留外层输入窗口及底部菜单。 + while(detailStack->count() > 1) delete detailStack->widget(1); + m_modeCombos.clear(); m_logChecks.clear(); m_numSpins.clear(); + m_modelSpins.clear(); m_minSpins.clear(); m_maxSpins.clear(); + m_valueTables.clear(); m_unitCombos.clear(); + m_numLabels.clear(); m_minLabels.clear(); m_maxLabels.clear(); + m_distributionCombos.clear(); m_distributionPanels.clear(); m_distributionPlots.clear(); + populateTreeWidget(); + createDetailPages(); + loadDataToUI(); m_loading = false; - updateModelCount(); + onTreeItemChanged(nullptr, 0); + onResultsChanged(); } void nmWxSensitive::loadDataToUI(bool refreshRangesOnly) @@ -1566,9 +1689,17 @@ void nmWxSensitive::loadDataToUI(bool refreshRangesOnly) m_numSpins[idx]->setValue(qMax(1, variable.getNumber())); } // 已打开窗口沿用原显示单位,避免手动表格的数值被换成另一种单位解释。 - const QString unit = refreshRangesOnly ? m_unitLabels[idx]->text() : variable.getModelValue().getUnit(); + const QString unit = nmParameterField::resolveUnitSpelling( + refreshRangesOnly ? m_unitCombos[idx]->currentText() : variable.getModelValue().getUnit()); variable.getModelValue().setUnit(unit); - m_unitLabels[idx]->setText(unit); + QComboBox* unitCombo = m_unitCombos[idx]; + unitCombo->clear(); + iUnitGroup* unitGroup = iUnitHelper::getUnitGroupByUnit( + nmParameterField::resolveUnitSpelling(samplingBaseUnit(name))); + if (unitGroup) unitCombo->addItems(unitGroup->getAllUnitNames()); + if (unitCombo->findText(unit) < 0) unitCombo->addItem(unit); + unitCombo->setCurrentIndex(unitCombo->findText(unit)); + unitCombo->setVisible(!unit.isEmpty()); double model = variable.getModelValue().getValue().toDouble(); double minimum = variable.getMinValue().getValue().toDouble(); double maximum = variable.getMaxValue().getValue().toDouble(); @@ -1583,7 +1714,7 @@ void nmWxSensitive::loadDataToUI(bool refreshRangesOnly) variable.m_distributionMin, variable.m_distributionMax}; for(int field = 0; field < 5; ++field) { double display = distributionValues[field]; - convertSamplingValue(name, display, samplingBaseUnit(name), unit, display); + convertSamplingValue(name, display, samplingBaseUnit(name), unit, display, field == 1); setSamplingEditValue(m_distributionPanels[idx]->findChild(distributionFields[field]), display); } double displayMin = variable.getModelValue().getMinValue().toDouble(); @@ -1689,8 +1820,9 @@ bool nmWxSensitive::saveDataFromUI() const QString name = variable.getVarName(); const int idx = findVariableIndex(variable); if (idx < 0 || !isSupportedSamplingVariable(name)) continue; - const QString unit = m_unitLabels[idx]->text(); + const QString unit = m_unitCombos[idx]->currentText(); const QString baseUnit = samplingBaseUnit(name); + variable.getModelValue().setUnit(unit); bool valid = true; if(candidate.getCalculationType() == nmDataSensitive::CALC_MONTE_CARLO) { double median = 0.0; @@ -1764,15 +1896,21 @@ void nmWxSensitive::setupUI() { setWindowTitle(tr("Sensitivity")); setMinimumSize(900, 550); - // 默认放大窗口,同时为屏幕边缘和窗口标题栏留出空间。 + setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); + // 适当加宽窗口,为整页单位下拉框和分布图保留空间。 const QSize available = QApplication::desktop()->availableGeometry(this).size() - QSize(60, 80); - resize(QSize(1250, 760).boundedTo(available)); + resize(QSize(1120, 660).boundedTo(available)); + // 沿用储层参数窗口的分组框、内容边距和底部按钮间距。 QVBoxLayout *mainLayout = new QVBoxLayout(this); + mainLayout->setContentsMargins(12, 10, 12, 0); + mainLayout->setSpacing(8); // ===== 顶部:Calculation type ===== - QHBoxLayout *calcTypeLayout = new QHBoxLayout(); - QLabel *calcTypeLabel = new QLabel(tr("Calculation type:"), this); + QGroupBox* calcTypeGroup = new QGroupBox(tr("Calculation type:"), this); + QHBoxLayout *calcTypeLayout = new QHBoxLayout(calcTypeGroup); + calcTypeLayout->setContentsMargins(10, 10, 10, 10); + calcTypeLayout->setSpacing(8); calculationTypeCombo = new QComboBox(this); calculationTypeCombo->addItem(tr("Deterministic"), nmDataSensitive::CALC_DETERMINISTIC); calculationTypeCombo->addItem(tr("Deterministic multivariate"), nmDataSensitive::CALC_DETERMINISTIC_MULTIVARIATE); @@ -1784,58 +1922,20 @@ void nmWxSensitive::setupUI() m_improveSettingsButton->setFixedHeight(calculationTypeCombo->sizeHint().height()); m_improveSettingsButton->hide(); - calcTypeLayout->addWidget(calcTypeLabel); calcTypeLayout->addWidget(calculationTypeCombo); calcTypeLayout->addWidget(m_improveSettingsButton); calcTypeLayout->addStretch(); - mainLayout->addLayout(calcTypeLayout); + mainLayout->addWidget(calcTypeGroup); // ===== 中间:左 Variables 面板 + 右 detailStack ===== QSplitter *centerSplitter = new QSplitter(Qt::Horizontal, this); centerSplitter->setChildrenCollapsible(false); // 不允许把某一侧完全折叠 centerSplitter->setHandleWidth(4); // 中间拖动条宽度 - centerSplitter->setStyleSheet( - "QSplitter::handle:horizontal {" - " background-color: #C0C0C0;" - "}" - "QSplitter::handle:horizontal:hover {" - " background-color: #A0A0A0;" - "}" - ); - - // --- 左侧:Variables 面板(QFrame + 标题栏 + Tree)--- - QFrame *variablesPanel = new QFrame(this); - variablesPanel->setFrameShape(QFrame::StyledPanel); - variablesPanel->setFrameShadow(QFrame::Raised); - variablesPanel->setMinimumWidth(230); - + // 左侧参数树使用标准分组框,样式交给主软件统一处理。 + QGroupBox *variablesPanel = new QGroupBox(tr("Variables"), this); + variablesPanel->setMinimumWidth(200); QVBoxLayout *variablesPanelLayout = new QVBoxLayout(variablesPanel); - variablesPanelLayout->setContentsMargins(0, 0, 0, 0); - variablesPanelLayout->setSpacing(0); - - // 标题栏 - QWidget *varHeader = new QWidget(variablesPanel); - varHeader->setFixedHeight(24); - varHeader->setAutoFillBackground(true); - { - QPalette pal = varHeader->palette(); - pal.setColor(QPalette::Window, - palette().color(QPalette::Midlight)); - varHeader->setPalette(pal); - } - - QHBoxLayout *varHeaderLayout = new QHBoxLayout(varHeader); - varHeaderLayout->setContentsMargins(6, 0, 6, 0); - varHeaderLayout->setSpacing(0); - - QLabel *varTitle = new QLabel(tr("Variables"), varHeader); - varTitle->setAlignment(Qt::AlignVCenter | Qt::AlignLeft); - QFont f = varTitle->font(); - f.setBold(true); - varTitle->setFont(f); - - varHeaderLayout->addWidget(varTitle); - varHeaderLayout->addStretch(); + variablesPanelLayout->setContentsMargins(10, 10, 10, 10); // Tree 区域 variablesTree = new QTreeWidget(variablesPanel); @@ -1843,7 +1943,6 @@ void nmWxSensitive::setupUI() variablesTree->setFrameShape(QFrame::NoFrame); // 外层已经有 frame variablesTree->setMinimumHeight(350); - variablesPanelLayout->addWidget(varHeader); variablesPanelLayout->addWidget(variablesTree, 1); // 把左侧 panel 加进 splitter @@ -1869,12 +1968,14 @@ void nmWxSensitive::setupUI() // 左边宽度基本固定,右边自适应 centerSplitter->setStretchFactor(0, 0); centerSplitter->setStretchFactor(1, 1); - centerSplitter->setSizes(QList() << 260 << 960); + centerSplitter->setSizes(QList() << 220 << 860); mainLayout->addWidget(centerSplitter, 1); // ===== 底部:Total number of models + 按钮 ===== QHBoxLayout *bottomLayout = new QHBoxLayout(); + bottomLayout->setContentsMargins(4, 5, 4, 5); + bottomLayout->setSpacing(8); QLabel *totalLabel = new QLabel(tr("Total number of models:"), this); modelCountLabel = new QLabel(tr("0"), this); @@ -1898,7 +1999,20 @@ void nmWxSensitive::setupUI() generateButton = new QPushButton(tr("Generate"), this); cancelButton = new QPushButton(tr("Cancel"), this); - + generateButton->setIcon(zxLoadIcon("OK")); + cancelButton->setIcon(zxLoadIcon("Cancel")); + + // 查看已有计算结果,不改变采样配置,也不重新求解。 + m_resultPlotsButton = new QPushButton(tr("Result plots"), this); + m_resultPlotsButton->setObjectName("nmSensitivityResultPlots"); + QMenu* resultMenu = new QMenu(m_resultPlotsButton); + resultMenu->addAction(tr("Loglog plot"))->setData(LoglogResult); + resultMenu->addAction(tr("History plot"))->setData(HistoryResult); + m_histogramResultAction = resultMenu->addAction(tr("Histogram")); + m_histogramResultAction->setData(HistogramResult); + m_resultPlotsButton->setMenu(resultMenu); + connect(resultMenu, SIGNAL(triggered(QAction*)), this, SLOT(onResultPlotTriggered(QAction*))); + bottomLayout->addWidget(m_resultPlotsButton); bottomLayout->addWidget(generateButton); bottomLayout->addWidget(cancelButton); @@ -2032,48 +2146,22 @@ QWidget *nmWxSensitive::createVariablePage(const QString &varName) pageLayout->setContentsMargins(0, 0, 0, 0); pageLayout->setSpacing(0); - // ===== 整个 Sampling 面板:QFrame + 标题栏 + 内容 ===== - QFrame *samplingPanel = new QFrame(page); - samplingPanel->setFrameShape(QFrame::StyledPanel); - samplingPanel->setFrameShadow(QFrame::Raised); - + // 采样页与左侧参数树统一使用标准分组框。 + QGroupBox *samplingPanel = new QGroupBox(tr("Sampling %1").arg(varName), page); QVBoxLayout *panelLayout = new QVBoxLayout(samplingPanel); - panelLayout->setContentsMargins(0, 0, 0, 0); - panelLayout->setSpacing(0); - - // ---- 标题栏:Sampling Xxx ---- - QWidget *header = new QWidget(samplingPanel); - header->setFixedHeight(24); - header->setAutoFillBackground(true); - { - QPalette pal = header->palette(); - pal.setColor(QPalette::Window, - palette().color(QPalette::Midlight)); - header->setPalette(pal); - } - - QHBoxLayout *headerLayout = new QHBoxLayout(header); - headerLayout->setContentsMargins(6, 0, 6, 0); - headerLayout->setSpacing(0); - - QLabel *title = new QLabel(tr("Sampling %1").arg(varName), header); - QFont tf = title->font(); - tf.setBold(true); - title->setFont(tf); - headerLayout->addWidget(title); - headerLayout->addStretch(); - - panelLayout->addWidget(header); + panelLayout->setContentsMargins(10, 10, 10, 10); + panelLayout->setSpacing(8); // ---- 内容区:左参数 + 右表格 ---- QWidget *content = new QWidget(samplingPanel); QHBoxLayout *contentLayout = new QHBoxLayout(content); - contentLayout->setContentsMargins(6, 0, 6, 6); + contentLayout->setContentsMargins(0, 0, 0, 0); contentLayout->setSpacing(12); // 左:参数区(GridLayout) QGridLayout *paramLayout = new QGridLayout(); - paramLayout->setVerticalSpacing(6); + paramLayout->setVerticalSpacing(8); + paramLayout->setHorizontalSpacing(8); int row = 0; // Mode + Log? @@ -2091,7 +2179,6 @@ QWidget *nmWxSensitive::createVariablePage(const QString &varName) distributionCombo->setObjectName("sensitivityDistribution_" + varName); distributionCombo->addItems(QStringList() << tr("Normal") << tr("Lognormal") << tr("Truncated normal") << tr("Truncated lognormal") << tr("Uniform") << tr("Triangular")); - distributionCombo->setFixedWidth(180); modeRowLayout->addWidget(distributionCombo); modeRowLayout->addWidget(logCheck); modeRowLayout->addStretch(); @@ -2111,11 +2198,6 @@ QWidget *nmWxSensitive::createVariablePage(const QString &varName) paramLayout->addWidget(numSpin, row, 1); ++row; - // 模式、数量与下方采样参数之间留出约三行空白。 - int gapRow = row; - paramLayout->setRowMinimumHeight(gapRow, numSpin->sizeHint().height() * 3); - ++row; - // Model value + 单位 QLabel *modelLabel = new QLabel(tr("Model value:"), content); QLineEdit *modelSpin = new QLineEdit(content); @@ -2123,13 +2205,18 @@ QWidget *nmWxSensitive::createVariablePage(const QString &varName) // 基准值来自真实模型,只作参照;输入框支持科学计数法和完整精度。 modelSpin->setReadOnly(true); - QLabel *unitLabel = new QLabel(tr(""), content); // ⭐ 单位也从数据加载 + // 当前参数整页共用一个单位,下拉选项和换算均复用框架单位组。 + QComboBox *unitCombo = new QComboBox(content); + unitCombo->setObjectName("sensitivityUnit_" + varName); + unitCombo->setMinimumWidth(86); + unitCombo->setMaximumWidth(120); + unitCombo->setFixedHeight(25); QWidget *modelRowWidget = new QWidget(content); QHBoxLayout *modelRowLayout = new QHBoxLayout(modelRowWidget); modelRowLayout->setContentsMargins(0, 0, 0, 0); modelRowLayout->addWidget(modelSpin); - modelRowLayout->addWidget(unitLabel); + modelRowLayout->addWidget(unitCombo); modelRowLayout->addStretch(); paramLayout->addWidget(modelLabel, row, 0); @@ -2140,9 +2227,8 @@ QWidget *nmWxSensitive::createVariablePage(const QString &varName) QWidget* distributionPanel = new QWidget(content); QGridLayout* distributionLayout = new QGridLayout(distributionPanel); distributionLayout->setContentsMargins(0, 0, 0, 0); - distributionLayout->setHorizontalSpacing(6); + distributionLayout->setHorizontalSpacing(8); distributionLayout->setVerticalSpacing(0); - distributionLayout->setColumnMinimumWidth(0, modelLabel->sizeHint().width()); const int fieldHeight = modelSpin->sizeHint().height(); // Mean 与三角分布的 Mode 共用一行,其余字段保持固定位置。 distributionPanel->setFixedHeight(fieldHeight * 4 + 6 * 3); @@ -2182,9 +2268,17 @@ QWidget *nmWxSensitive::createVariablePage(const QString &varName) paramLayout->addWidget(maxSpin, row, 1); ++row; - // 统一编辑框宽度 - int fullWidth = modelSpin->sizeHint().width(); - int editWidth = qMax(150, fullWidth); + // 基本参数与分布参数使用相同标签列宽、列间距和输入宽度,保证上下对齐。 + QList labels; + labels << modeLabel << numLabel << modelLabel << minLabel << maxLabel; + labels.append(distributionPanel->findChildren()); + int labelWidth = 0; + foreach(QLabel* label, labels) labelWidth = qMax(labelWidth, label->sizeHint().width()); + foreach(QLabel* label, labels) label->setFixedWidth(labelWidth); + const int editWidth = qMax(180, modelSpin->sizeHint().width()); + distributionCombo->setFixedWidth(editWidth); + foreach(QLineEdit* edit, distributionPanel->findChildren()) + edit->setFixedWidth(editWidth); modeCombo->setFixedWidth(editWidth); numSpin->setFixedWidth(editWidth); @@ -2200,7 +2294,7 @@ QWidget *nmWxSensitive::createVariablePage(const QString &varName) QWidget *paramWidget = new QWidget(content); QVBoxLayout *leftVBox = new QVBoxLayout(paramWidget); - leftVBox->setContentsMargins(0, 6, 0, 0); + leftVBox->setContentsMargins(0, 0, 0, 0); leftVBox->addLayout(paramLayout); leftVBox->addStretch(); @@ -2212,27 +2306,40 @@ QWidget *nmWxSensitive::createVariablePage(const QString &varName) headers << "" << tr("Values"); valuesTable->setHorizontalHeaderLabels(headers); - valuesTable->verticalHeader()->setVisible(false); + // 沿用编辑井的行号、隔行底色和网格样式,保留采样行的箭头标记。 + valuesTable->verticalHeader()->setVisible(true); + valuesTable->verticalHeader()->setMovable(false); + valuesTable->verticalHeader()->setDefaultAlignment(Qt::AlignCenter); + valuesTable->verticalHeader()->setMinimumWidth(18); QHeaderView *hh = valuesTable->horizontalHeader(); hh->setResizeMode(QHeaderView::Fixed); hh->setHighlightSections(false); - // 箭头列固定,数值列在下方设置为填满加宽后的表格。 valuesTable->setColumnWidth(0, 15); - valuesTable->setStyleSheet( - "QHeaderView::section {" - " border-top: 0px;" - " border-left: 0px;" - " border-right: 1px solid lightgray;" - " border-bottom: 1px solid lightgray;" - "}" - "QTableCornerButton::section {" - " border-top: 0px;" - " border-left: 0px;" - " border-right: 1px solid lightgray;" - " border-bottom: 1px solid lightgray;" - "}" - ); - + valuesTable->setAlternatingRowColors(true); + valuesTable->setStyleSheet( + "QTableWidget {" + " background-color: palette(base);" + " alternate-background-color: rgb(232, 232, 232);" + " gridline-color: palette(midlight);" + " border: 1px solid palette(mid);" + "}" + "QHeaderView {" + " background-color: palette(button);" + " color: palette(button-text);" + "}" + "QHeaderView::section {" + " background-color: palette(button);" + " color: palette(button-text);" + " border: none;" + " border-right: 1px solid palette(mid);" + " border-bottom: 1px solid palette(mid);" + "}" + "QTableCornerButton::section {" + " background-color: palette(base);" + " border: none;" + " border-right: 1px solid palette(mid);" + " border-bottom: 1px solid palette(mid);" + "}"); valuesTable->horizontalHeader()->setStretchLastSection(true); valuesTable->setEditTriggers(QAbstractItemView::DoubleClicked); valuesTable->setSelectionBehavior(QAbstractItemView::SelectRows); @@ -2243,22 +2350,27 @@ QWidget *nmWxSensitive::createVariablePage(const QString &varName) valuesTable->setItemDelegateForColumn(1, new RightAlignDelegate(valuesTable)); - // 初始空表的列宽尚未稳定,直接固定容器宽度,不从未显示的表头反算。 - const int tableWidth = 190; - valuesTable->setFixedWidth(tableWidth); + // 与编辑井一样使用可拖动分栏,表格和分布图共用右侧空间。 + QSplitter* samplingSplitter = new QSplitter(Qt::Horizontal, content); + samplingSplitter->setChildrenCollapsible(false); + samplingSplitter->setHandleWidth(6); + // 分栏仍可拖动,但不绘制参数与图表之间的灰色竖线。 + samplingSplitter->setStyleSheet("QSplitter::handle { background: transparent; border: none; }"); + samplingSplitter->addWidget(paramWidget); - QWidget *tableContainer = new QWidget(content); + QWidget *tableContainer = new QWidget(samplingSplitter); QVBoxLayout *tableLayout = new QVBoxLayout(tableContainer); tableLayout->setContentsMargins(0, 0, 0, 0); tableLayout->setSpacing(0); tableLayout->addWidget(valuesTable); - tableContainer->setFixedWidth(tableWidth); - - contentLayout->addWidget(paramWidget, 1); - contentLayout->addStretch(); - contentLayout->addWidget(tableContainer, 0, Qt::AlignRight); - SensitivityDistributionPlot* distributionPlot = new SensitivityDistributionPlot(content); - contentLayout->addWidget(distributionPlot, 2); + valuesTable->setMinimumWidth(190); + SensitivityDistributionPlot* distributionPlot = new SensitivityDistributionPlot(tableContainer); + tableLayout->addWidget(distributionPlot); + samplingSplitter->addWidget(tableContainer); + samplingSplitter->setStretchFactor(0, 1); + samplingSplitter->setStretchFactor(1, 0); + samplingSplitter->setSizes(QList() << 630 << 210); + contentLayout->addWidget(samplingSplitter); panelLayout->addWidget(content); pageLayout->addWidget(samplingPanel); @@ -2272,7 +2384,8 @@ QWidget *nmWxSensitive::createVariablePage(const QString &varName) m_minSpins.append(minSpin); m_maxSpins.append(maxSpin); m_valueTables.append(valuesTable); - m_unitLabels.append(unitLabel); + m_unitCombos.append(unitCombo); + connect(unitCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(onSamplingUnitChanged())); m_numLabels.append(numLabel); m_minLabels.append(minLabel); m_maxLabels.append(maxLabel); @@ -2314,13 +2427,23 @@ void nmWxSensitive::updateValuesForPage(int idx) m_maxLabels[idx]->setVisible(!monteCarlo); m_minSpins[idx]->setVisible(!monteCarlo); m_maxSpins[idx]->setVisible(!monteCarlo); - m_valueTables[idx]->parentWidget()->setVisible(!monteCarlo); + m_valueTables[idx]->setVisible(!monteCarlo); m_distributionCombos[idx]->setVisible(monteCarlo); m_distributionPanels[idx]->setVisible(monteCarlo); m_distributionPlots[idx]->setVisible(monteCarlo); - // Monte-Carlo 参数区只占所需宽度,窗口增宽时优先扩展分布图。 - QHBoxLayout* contentLayout = static_cast(m_distributionPlots[idx]->parentWidget()->layout()); - contentLayout->setStretch(0, monteCarlo ? 0 : 1); + // 表格采用较窄的默认宽度;分布图让参数区仅占所需宽度,避免沿用表格分栏。 + // 只在布局类型切换时调整,编辑参数时保留用户拖动后的宽度。 + QSplitter* splitter = static_cast(m_valueTables[idx]->parentWidget()->parentWidget()); + const QVariant previousLayout = splitter->property("monteCarloLayout"); + if (!previousLayout.isValid() || previousLayout.toBool() != monteCarlo) { + splitter->setProperty("monteCarloLayout", monteCarlo); + splitter->setStretchFactor(0, monteCarlo ? 0 : 1); + splitter->setStretchFactor(1, monteCarlo ? 1 : 0); + const int availableWidth = qMax(840, splitter->width() - splitter->handleWidth()); + const int parameterWidth = monteCarlo ? splitter->widget(0)->minimumSizeHint().width() + : availableWidth - 210; + splitter->setSizes(QList() << parameterWidth << availableWidth - parameterWidth); + } if(monteCarlo) { updateDistributionPage(idx); return; } // 自动模式由范围生成只读表格;手动模式保留每行值,不因选中行而重算。 QTableWidget* table = m_valueTables[idx]; @@ -2339,7 +2462,7 @@ void nmWxSensitive::updateValuesForPage(int idx) } QVector samples; const QString name = variable.getVarName(); - const QString unit = m_unitLabels[idx]->text(); + const QString unit = m_unitCombos[idx]->currentText(); if (automatic) { bool minOk = false, maxOk = false; double minimum = samplingEditValue(m_minSpins[idx], &minOk); @@ -2380,7 +2503,7 @@ bool nmWxSensitive::readDistributionPage(int idx, nmDataSensitive::VariableSampl // 字段转换沿用现有参数单位,仅校验当前分布实际使用的字段。 variable.m_distribution = static_cast( m_distributionCombos[idx]->currentIndex()); - variable.m_modelValue.setUnit(m_unitLabels[idx]->text()); + variable.m_modelValue.setUnit(m_unitCombos[idx]->currentText()); double* fields[] = {&variable.m_mean, &variable.m_stdDev, &variable.m_peak, &variable.m_distributionMin, &variable.m_distributionMax}; const int distribution = variable.m_distribution; @@ -2392,7 +2515,7 @@ bool nmWxSensitive::readDistributionPage(int idx, nmDataSensitive::VariableSampl bool ok = false; double value = samplingEditValue(m_distributionPanels[idx]->findChild(distributionFields[field]), &ok); if(!ok || !qIsFinite(value) || !convertSamplingValue(variable.m_varName, value, - m_unitLabels[idx]->text(), samplingBaseUnit(variable.m_varName), *fields[field])) return false; + m_unitCombos[idx]->currentText(), samplingBaseUnit(variable.m_varName), *fields[field], field == 1)) return false; } return true; } @@ -2418,6 +2541,81 @@ void nmWxSensitive::updateDistributionPage(int idx) } } +void nmWxSensitive::onSamplingUnitChanged() +{ + if (m_loading) return; + QComboBox* combo = qobject_cast(sender()); + const int idx = m_unitCombos.indexOf(combo); + if (idx < 0) return; + for (int i = 0; i < m_sensitiveData.getVariableCount(); ++i) { + nmDataSensitive::VariableSampling& variable = m_sensitiveData.getVariable(i); + if (findVariableIndex(variable) != idx) continue; + const QString from = variable.getModelValue().getUnit(); + const QString to = combo->currentText(); + if (from == to) return; + + // 先换算当前界面草稿,全部成功后再更新,避免覆盖未提交的手动输入。 + QList edits; + edits << m_modelSpins[idx] << m_minSpins[idx] << m_maxSpins[idx]; + for (int field = 0; field < 5; ++field) + edits << m_distributionPanels[idx]->findChild(distributionFields[field]); + QVector values(edits.size()); + bool valid = true; + for (int field = 0; valid && field < edits.size(); ++field) { + bool ok = false; + const double value = samplingEditValue(edits[field], &ok); + valid = ok && convertSamplingValue(variable.m_varName, value, from, to, values[field], field == 4); + } + QTableWidget* table = m_valueTables[idx]; + QVector tableValues(table->rowCount()); + for (int row = 0; valid && row < table->rowCount(); ++row) { + QTableWidgetItem* item = table->item(row, 1); + if (!item || item->text().isEmpty()) continue; + bool ok = false; + const double value = item->data(Qt::UserRole).isValid() + ? item->data(Qt::UserRole).toDouble(&ok) : item->text().trimmed().toDouble(&ok); + valid = ok && convertSamplingValue(variable.m_varName, value, from, to, tableValues[row]); + } + if (!valid) { + combo->blockSignals(true); + combo->setCurrentIndex(combo->findText(from)); + combo->blockSignals(false); + double lower = variable.getModelValue().getMinValue().toDouble(); + double upper = variable.getModelValue().getMaxValue().toDouble(); + convertSamplingValue(variable.m_varName, lower, samplingBaseUnit(variable.m_varName), from, lower); + convertSamplingValue(variable.m_varName, upper, samplingBaseUnit(variable.m_varName), from, upper); + QMessageBox::warning(this, tr("Sensitivity"), + tr("%1: invalid sampling values. Allowed range: [%2, %3] %4. Check the sampling settings.") + .arg(variable.m_varName).arg(formatSamplingValue(lower, 6)) + .arg(formatSamplingValue(upper, 6)).arg(from)); + return; + } + + // 仅更新显示单位和显示值,基准采样数据及已生成的随机样本保持不变。 + m_loading = true; + variable.getModelValue().setUnit(to); + for (int field = 0; field < edits.size(); ++field) + setSamplingEditValue(edits[field], values[field]); + for (int row = 0; row < table->rowCount(); ++row) { + QTableWidgetItem* item = table->item(row, 1); + if (!item || item->text().isEmpty()) continue; + item->setData(Qt::UserRole, tableValues[row]); + item->setText(formatSamplingValue(tableValues[row], 3)); + } + double lower = variable.getModelValue().getMinValue().toDouble(); + double upper = variable.getModelValue().getMaxValue().toDouble(); + convertSamplingValue(variable.m_varName, lower, samplingBaseUnit(variable.m_varName), to, lower); + convertSamplingValue(variable.m_varName, upper, samplingBaseUnit(variable.m_varName), to, upper); + const QString rangeHint = tr("Allowed range: [%1, %2] %3") + .arg(formatSamplingValue(lower, 6)).arg(formatSamplingValue(upper, 6)).arg(to); + m_minSpins[idx]->setToolTip(rangeHint); + m_maxSpins[idx]->setToolTip(rangeHint); + updateValuesForPage(idx); + m_loading = false; + return; + } +} + void nmWxSensitive::onSamplingEditingFinished() { // 输入结束后截断越界范围,再按六位有效数字显示,计算仍使用原始精度。 @@ -2433,7 +2631,7 @@ void nmWxSensitive::onSamplingEditingFinished() const QString name = variable.getVarName(); if (findVariableIndex(variable) != idx) continue; double lower = 0.0, upper = 0.0; - const QString unit = m_unitLabels[idx]->text(); + const QString unit = m_unitCombos[idx]->currentText(); const QString baseUnit = samplingBaseUnit(name); if (!samplingPhysicalRange(name, lower, upper) || !convertSamplingValue(name, value, unit, baseUnit, value)) return; @@ -2564,6 +2762,7 @@ void nmWxSensitive::onGenerateClicked() } m_pDataManager->updateSensitiveData(m_sensitiveData); + m_sourceData = m_pDataManager->getSensitiveData(); // 新任务准备成功后才替换上次临时结果,准备失败仍可保留旧结果。 delete m_pSensitivityTask; m_pSensitivityTask = task.take(); @@ -2582,7 +2781,7 @@ void nmWxSensitive::startSensitivityCalculation() connect(m_pSensitivityTask, SIGNAL(finished()), this, SLOT(onSensitivityFinished()), Qt::QueuedConnection); setCalculationRunning(true); - // 仅关闭参数界面;控制器及任务仍存活,结束后继续保留临时计算结果。 + // 计算期间隐藏输入窗口,任务结束后继续复用。 hide(); m_pSensitivityTask->start(); } @@ -2606,6 +2805,7 @@ void nmWxSensitive::setCalculationRunning(bool running) detailStack->setEnabled(!running); m_monteCarloCount->setEnabled(!running); previewButton->setEnabled(!running); + m_resultPlotsButton->setEnabled(!running && !m_sensitiveData.getResults().isNull()); cancelButton->setEnabled(!running); if(running) { generateButton->setEnabled(false); @@ -2651,6 +2851,16 @@ void nmWxSensitive::onResultsChanged() if(m_pDataManager && m_pDataManager->getSensitiveData()) results = m_pDataManager->getSensitiveData()->getResults(); m_sensitiveData.setResults(results); + m_resultPlotsButton->setEnabled(!m_calculationRunning && !results.isNull()); + m_histogramResultAction->setEnabled(!results.isNull() && + results->m_calcType == nmDataSensitive::CALC_MONTE_CARLO); +} + +void nmWxSensitive::onResultPlotTriggered(QAction* action) +{ + // 菜单按已生成批次开放,切换输入计算方法不改变旧结果可查看的图形。 + if(!action || m_calculationRunning || m_sensitiveData.getResults().isNull()) return; + emit sigShowSensitivityResult(action->data().toInt()); } void nmWxSensitive::onCalculationTypeChanged(int index) @@ -2672,9 +2882,16 @@ void nmWxSensitive::onImproveSettingsClicked() QStringList sampledParameters; foreach(const nmDataSensitive::VariableSampling& variable, m_sensitiveData.getVariables()) if(variable.m_enabled) sampledParameters.append(variable.parameterKey()); - nmWxAutomaticFitting dialog(this, &settings, sampledParameters); - if(dialog.exec() == QDialog::Accepted) { - m_sensitiveData.setImproveSettings(QSharedPointer(new nmSensitivityFitSettings(settings))); + if(m_improveSettingsDraft.isNull()) m_improveSettingsDraft = QSharedPointer(new nmSensitivityFitSettings); + *m_improveSettingsDraft = settings; + nmWxAutomaticFitting* dialog = findChild("nmSensitivityImproveSettings"); + if(!dialog) { + dialog = new nmWxAutomaticFitting(this, m_improveSettingsDraft.data(), sampledParameters); + dialog->setObjectName("nmSensitivityImproveSettings"); + dialog->setAttribute(Qt::WA_DeleteOnClose, false); + } else dialog->reloadSensitivitySettings(sampledParameters); + if(dialog->exec() == QDialog::Accepted) { + m_sensitiveData.setImproveSettings(QSharedPointer(new nmSensitivityFitSettings(*m_improveSettingsDraft))); updateModelCount(); } } @@ -2706,25 +2923,31 @@ void nmWxSensitive::onPreviewClicked() // 样本已在允许范围内生成,直接显示预览。 } // Saphir 风格的连续运行列表,组合数再大也不显示分页控件。 - QDialog dialog(this); - dialog.setWindowTitle(tr("Sensitivity Runs")); - dialog.setWindowFlags(dialog.windowFlags() & ~Qt::WindowContextHelpButtonHint); - dialog.setMinimumSize(420, 360); - dialog.resize(470, 650); - QVBoxLayout* layout = new QVBoxLayout(&dialog); - layout->setContentsMargins(16, 16, 16, 12); - layout->setSpacing(8); - m_previewView = new SensitivityRunsView(m_sensitiveData, createTriangleIcon(), &dialog); - layout->addWidget(m_previewView); - QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Close, Qt::Horizontal, &dialog); - buttons->setCenterButtons(true); - buttons->button(QDialogButtonBox::Close)->setMinimumWidth(110); - layout->addWidget(buttons); - connect(buttons, SIGNAL(rejected()), &dialog, SLOT(reject())); + QDialog* dialog = findChild("nmSensitivityPreview"); + if(!dialog) { + dialog = new QDialog(this); + dialog->setObjectName("nmSensitivityPreview"); + dialog->setAttribute(Qt::WA_DeleteOnClose, false); + dialog->setWindowTitle(tr("Sensitivity Runs")); + dialog->setWindowFlags(dialog->windowFlags() & ~Qt::WindowContextHelpButtonHint); + dialog->setMinimumSize(420, 360); + dialog->resize(470, 650); + QVBoxLayout* layout = new QVBoxLayout(dialog); + layout->setContentsMargins(16, 16, 16, 12); + layout->setSpacing(8); + QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Close, Qt::Horizontal, dialog); + buttons->setCenterButtons(true); + buttons->button(QDialogButtonBox::Close)->setMinimumWidth(110); + layout->addWidget(buttons); + connect(buttons, SIGNAL(rejected()), dialog, SLOT(reject())); + } + // 预览窗口保持不变,运行列表按本次采样重建,避免保留旧行数。 + delete m_previewView; + m_previewView = new SensitivityRunsView(m_sensitiveData, createTriangleIcon(), dialog); + qobject_cast(dialog->layout())->insertWidget(0, m_previewView); connect(m_previewView->verticalScrollBar(), SIGNAL(actionTriggered(int)), this, SLOT(onPreviewScrollAction(int))); - dialog.exec(); - m_previewView = nullptr; + dialog->exec(); } void nmWxSensitive::onPreviewScrollAction(int action)