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)