diff --git a/Bin/Config/Common/MenuDefines_Ribbon_cn.dat b/Bin/Config/Common/MenuDefines_Ribbon_cn.dat
index cd7a660..d99c42a 100644
--- a/Bin/Config/Common/MenuDefines_Ribbon_cn.dat
+++ b/Bin/Config/Common/MenuDefines_Ribbon_cn.dat
@@ -1 +1 @@
-77u/PD94bWwgcup_mpadmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4NCg0KPCEtLSDnvJbovpHkvbwzy/nlKggWE1MU3B5IHYyMDA2IFUgKGh0dHA6Ly93d3cuYWx0b3ZhLmNvbSkg55SxIGFueSAoYW55KSAtLT4NCjwhLS0qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqLS0+DQo8IS0tICAgIOacrOaWh+aho+eahOebrueahOaYr+W7uueri1dUQUnova/ku7bns7vnu5/nmoToj5zljZXlsYLmrKHlhbPns7so6ZKI5a+5UmliYm9u5qih5byPKSAgICAgICAgICAgICAgICAgICAgICAgLS0+DQo8IS0tICAgIEF1dGhvcihzKTogd2FuZ3pnICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC0tPg0KPCEtLSAgICBEYXRlOiAyMDI0MDcxOCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAtLT4NCjwhLS0qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqLS0+DQoNCjwhLS0qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqLS0+DQo8IS0tDQogICAgVGFiIOe6p+WIqw0KICAgICAgICBJRDogICAgICAgICAg5ZSv5LiA5qCH6K+GDQogICAgICAgIE5hbWXvvJogICAgICAg5ZCN56ew77yM6YCa5bi46Iux5paHDQogICAgICAgIEFsaWFz77yaICAgICAg5Yir5ZCN77yM6YCa5bi45Lit5paHDQogICAgICAgIEZpbGVNb2RlOiAgICDmmK/lkKbmlofku7ZNZW515qih5byP77yMMSBvciAwDQogICAgICAgIFZpc2libGXvvJogICAg5piv5ZCm5Y+v6KeB77yMMSBvciAwDQogICAgICAgIFRpcHPvvJogICAgICAg6L6F5Yqp6K+05piODQoNCiAgICAgICAgR3JvdXAg57qn5YirDQogICAgICAgICAgICBOYW1l77yaICAgICAgIOWQjeensO+8jOmAmuW4uOiLseaWhw0KICAgICAgICAgICAgQWxpYXPvvJogICAgICDliKvlkI3vvIzpgJrluLjkuK3mlocNCg0KICAgICAgICAgICAgQ21kIOe6p+WIqw0KICAgICAgICAgICAgICAgIElEOiAgICAgICAgICDllK/kuIDmoIfor4YNCiAgICAgICAgICAgICAgICBUeXBlOiAgICAgICAg5a+55bqU5o6n5Lu257G75Z6LOg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAw4oCU4oCU6buY6K6kQnV0dG9uDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIDHigJTigJTluKbkuIvmi4noj5zljZVCdXR0b24NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMuKAlOKAlENvbWJvQm94DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIDPigJTigJRDaGVja0JveA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICA04oCU4oCUUmFkaW9CdXR0b24NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgNeKAlOKAlFRleHQNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgNuKAlOKAlExhYmVsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIDfigJTigJRMaXN0V2lkZ2V0DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIDjigJTigJRMaW5lRWRpdA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICA54oCU4oCU5YqI5YiG5oyJ6ZKuDQogICAgICAgICAgICAgICAgTmFtZe+8miAgICAgICDlkI3np7DvvIzpgJrluLjoi7HmlocNCiAgICAgICAgICAgICAgICBBbGlhc++8miAgICAgIOWIq+WQje+8jOmAmuW4uOS4reaWhw0KICAgICAgICAgICAgICAgIEljb27vvJogICAgICAg5Zu+5qCHDQogICAgICAgICAgICAgICAgU2hvcnRLZXnvvJogICDlv6vmjbfplK4NCiAgICAgICAgICAgICAgICBCb3VuZHM6ICAgICAg5L2N572u5L+h5oGv77yM5YWo5piv5pW05pWw77yM5ZyoR3JpZExheW91dOS4rQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoMCwwLDEsMikgKDAsMCkg5YiG5Yir5Li6eHl3aA0KICAgICAgICAgICAgICAgIEV4dEluZm86ICAgICDmianlsZXkv6Hmga/vvIzlpoLmk43kvZzlr7nosaHnmoTooajlkI0s5LiL5ouJ6YCJ6aG5562JDQogICAgICAgICAgICAgICAgRXh0TmFtZXM6ICAgIOaJqeWxleS/oeaBr+WvueW6lOeahE5hbWXvvIzlpoLkuIvmi4lidXR0b27lr7nlupTnmoROYW1lDQogICAgICAgICAgICAgICAgVGlwc++8miAgICAgICDovoXliqnor7TmmI4NCi0tPg0KPCEtLSoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiotLT4NCg0KPFJpYmJvbj4NCg0KICAgIDxUYWIgSUQ9IjEiIE5hbWU9IlByb2pNYW5hZ2VyIiBBbGlhcz0i6aG555uu566h55CGKFApIiBGaWxlTW9kZT0iMSIgPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJQcm9qZWN0IiBBbGlhcz0i5paH5Lu2Ij4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjEwMDAiIE5hbWU9IkFwcEhvbWUiIEFsaWFzPSIiIEljb249IkFwcEhvbWUxMjgiIC8+DQogICAgICAgICAgICA8Q21kIElEPSItMSIgTmFtZT0iU2VwYXJhdG9yIiBBbGlhcz0i5YiG6ZqU56ymIiBUaXBzPSIiIC8+DQogICAgICAgICAgICA8Q21kIElEPSIxMDAxIiBOYW1lPSJQcm9qTmV3IiBBbGlhcz0i5paw5bu66aG555uuIiBTaG9ydEtleT0iQ3RybCtOIiBJY29uPSJOZXdQcm9qIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMTAwMiIgTmFtZT0iUHJvak9wZW4iIEFsaWFzPSLmiZPlvIDpobnnm64iIFNob3J0S2V5PSJDdHJsK08iIEljb249Ik9wZW5Qcm9qIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMTAwMyIgTmFtZT0iUHJvakNsb3NlIiBBbGlhcz0i5YWz6Zet6aG555uuIiBJY29uPSJDbG9zZVByb2oiIC8+DQogICAgICAgICAgICA8Q21kIElEPSItMSIgTmFtZT0iU2VwYXJhdG9yIiBBbGlhcz0i5YiG6ZqU56ymIiBUaXBzPSIiIC8+DQogICAgICAgICAgICA8Q21kIElEPSIxMDA1IiBOYW1lPSJQcm9qU2F2ZSIgQWxpYXM9IuS/neWtmOmhueebriIgU2hvcnRLZXk9IkN0cmwrUyIgSWNvbj0iU2F2ZVByb2oiIC8+DQogICAgICAgICAgICA8Q21kIElEPSIxMDA2IiBOYW1lPSJQcm9qU2F2ZUFzIiBBbGlhcz0i6aG555uu5Y+m5a2YIiBJY29uPSJTYXZlYXMiIC8+DQogICAgICAgICAgICA8Q21kIElEPSIxMDA3IiBOYW1lPSJQcm9qQ29uZmlnIiBBbGlhcz0i6aG555uu5L+h5oGvIiBJY29uPSJQcm9qSW5mbyIgLz4NCg0KICAgICAgICAgICAgPENtZCBJRD0iLTEiIE5hbWU9IlNlcGFyYXRvciIgQWxpYXM9IuWIhumalOespiIgVGlwcz0iIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMTAwMDIiIE5hbWU9IkhlbHAiIEFsaWFzPSLluK7liqkoSCkiIEljb249IkhlbHAiIC8+DQogICAgICAgICAgICA8Q21kIElEPSIxMDAwMyIgTmFtZT0iQWJvdXQiIEFsaWFzPSLlhbPkuo4oQSkiIEljb249IldUQUlBYm91dCIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjEwMDA4IiBOYW1lPSJVcGRhdGVMaXN0cyIgQWxpYXM9IuabtOaWsOWIl+ihqChJKSIgSWNvbj0iVXBkYXRlTGlzdHMiIC8+DQogICAgICAgICAgICA8Q21kIElEPSItMSIgTmFtZT0iU2VwYXJhdG9yIiBBbGlhcz0i5YiG6ZqU56ymIiBUaXBzPSIiIC8+DQogICAgICAgICAgICA8Q21kIElEPSIxMDEwIiBOYW1lPSJBcHBRdWl0IiBBbGlhcz0i6YCA5Ye6KFgpIiBJY29uPSJDbG9zZSIgLz4NCiAgICAgICAgPC9Hcm91cD4NCiAgICA8L1RhYj4NCg0KICAgIDxUYWIgSUQ9IjAiIE5hbWU9IldlbENvbWUiIEFsaWFzPSLlvIDlp4soTykiID4NCg0KICAgICAgICA8R3JvdXAgTmFtZT0iRGF0YU1hbmFnZXIiIEFsaWFzPSLmlbDmja7lh4blpIciPg0KICAgICAgICAgICAgPENtZCBJRD0iMTA5OSIgQm91bmRzPSIwLDAsMiwxIiBOYW1lPSJXZWxsTmV3IiBBbGlhcz0i5paw5bu65LqVKFcpIiBJY29uPSJXZWxsTmV3IiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMjAwNSIgQm91bmRzPSIwLDEsMiwxIiBOYW1lPSJEYXRhUmF0ZSIgQWxpYXM9Iua1gemHj+aVsOaNrihRKSIgRXh0SW5mbz0iUF9EQVRBX0dBVUdFX0YiIEljb249IlJhdGVEYXRhIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMjAwNiIgQm91bmRzPSIwLDIsMiwxIiBOYW1lPSJEYXRhUHJlIiBBbGlhcz0i5Y6L5Yqb5pWw5o2uKFApIiBFeHRJbmZvPSJQX0RBVEFfR0FVR0VfUCIgSWNvbj0iUHJlc3N1cmVEYXRhIiAvPg0KICAgICAgICA8L0dyb3VwPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJBbmFsRWRpdCIgQWxpYXM9IuWIhuaekOeuoeeQhiI+DQogICAgICAgICAgICA8Q21kIElEPSIzMDA2IiBCb3VuZHM9IjAsMCwyLDEiIE5hbWU9IkFuYWxOZXciIEFsaWFzPSLmlrDlu7rliIbmnpAiIEljb249IkpvYk5ldyIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjMwMDciIEJvdW5kcz0iMCwxLDIsMSIgTmFtZT0iQW5hbEVkaXQiIEFsaWFzPSLliIbmnpDnrqHnkIYiIEljb249IkpvYkVkaXQiIFZpc2libGU9IjAiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI5MTAxIiBCb3VuZHM9IjAsMSIgTmFtZT0iVmlzaWJsZUFuYWxCYXNpYyIgQWxpYXM9IuWfuuehgOS/oeaBryIgSWNvbj0iSW5wdXRCYXNpYyIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkxMDIiIEJvdW5kcz0iMSwxIiBOYW1lPSJWaXNpYmxlQW5hbFBWVCIgQWxpYXM9IlBWVOaVsOaNriIgSWNvbj0iSW5wdXRGbHVpZCIgLz4NCiAgICAgICAgPC9Hcm91cD4NCg0KICAgICAgICA8R3JvdXAgTmFtZT0iQW5hbHl0aWNhbCIgQWxpYXM9Iua1geWKqOauteWIhuaekCI+DQogICAgICAgICAgICA8Q21kIElEPSIzMDAzIiBCb3VuZHM9IjAsMCwyLDEiIE5hbWU9IkFuYWxQRiIgQWxpYXM9Iua1geWKqOautemAieaLqSIgRXh0SW5mbz0iUEYiIEljb249IlBGIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMzAwNCIgQm91bmRzPSIwLDEsMiwxIiBOYW1lPSJBbmFsRmxvd1NlZyIgQWxpYXM9Iua1geWKqOauteWIhuaekCIgSWNvbj0iRmxvd1BlcmlvZCIgLz4NCiAgICAgICAgPC9Hcm91cD4NCg0KICAgICAgICA8R3JvdXAgTmFtZT0iQW5hbHl0aWNhbCIgQWxpYXM9Iuino+mHiuaLn+WQiCI+DQoNCiAgICAgICAgICAgIDxDbWQgSUQ9IjMxMDUiIEJvdW5kcz0iMCwwLDIsMSIgTmFtZT0iRGVjb252b2x2IiBBbGlhcz0i5Y+N6KS256evIiBJY29uPSJEZWNvbnZvbHYiIFZpc2libGU9IjAiIC8+DQogICAgICAgICAgICA8Q21kIElEPSIzMTAxIiBCb3VuZHM9IjAsMSwyLDEiIE5hbWU9IkZpdE1vZGVsIiBBbGlhcz0i6Kej5p6Q6KejIiBJY29uPSJGaXRNb2RlbCIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjMxMDQiIEJvdW5kcz0iMCwyLDIsMSIgTmFtZT0ibm1GaXRNb2RlbCIgQWxpYXM9IuaVsOWAvOinoyIgSWNvbj0iRml0TW9kZWwiIC8+DQoNCiAgICAgICAgICAgIDxDbWQgSUQ9IjMxMDIiIEJvdW5kcz0iMCwzLDIsMSIgTmFtZT0iQXV0b0ZpdCIgQWxpYXM9IuiHquWKqOaLn+WQiCIgSWNvbj0iQXV0b0ZpdCIgLz4NCiAgICAgICA8L0dyb3VwPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJOdW1lcmljYWwiIEFsaWFzPSLlnLDotKjlu7rmqKEoRGVidWcpIiBWaXNpYmxlPSIwIj4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjUwMDIiIEJvdW5kcz0iMCwwLDIsMSIgTmFtZT0iUHJvcGVydHlMb2FkIiBBbGlhcz0i5bGe5oCn5a+85YWlIiBJY29uPSJQcmVwYXJlR3JpZCIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjUxMDIiIEJvdW5kcz0iMCwxLDIsMSIgTmFtZT0iUnVuR3JpZCIgQWxpYXM9Iue9keagvOWIkuWIhiIgSWNvbj0iUGxhdGVGaXQiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI1MjAxIiBCb3VuZHM9IjAsMiwyLDEiIE5hbWU9IkFuYWxNYXAiIEFsaWFzPSLorqHnrpciIEljb249IlJ1bkV4IiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iNTIwMiIgQm91bmRzPSIwLDMsMiwxIiBOYW1lPSJBbmFsUEYiIEFsaWFzPSLovoXliqnmi5/lkIgiIEV4dEluZm89IlBGIiBJY29uPSJSdW5PdGhlciIgVmlzaWJsZT0iMCIvPg0KICAgICAgIDwvR3JvdXA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9IldlbGxNYXAiIEFsaWFzPSLkupXkvY3lm74iPg0KICAgICAgICAgICAgPENtZCBJRD0iMzAwOCIgQm91bmRzPSIwLDAsMiwxIiBOYW1lPSJBbmFsTWFwIiBBbGlhcz0i5LqV5L2N5Zu+IiBJY29uPSJNYXAyRCIgVmlzaWJsZT0iMSIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjMwMTgiIEJvdW5kcz0iMCwxLDIsMSIgTmFtZT0iQW5hbEludGVyZmVyZSIgQWxpYXM9IuW5suaJsOiuvuWumiIgSWNvbj0iTWFwMkQiIFZpc2libGU9IjAiIC8+DQogICAgICAgIDwvR3JvdXA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9IldpbmRvdyIgQWxpYXM9Iueql+WPo+aYvuekuihEZWJ1ZykiIFZpc2libGU9IjAiID4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkwMDIiIEJvdW5kcz0iMCwwIiBOYW1lPSJWaXNpYmxlTW9kZWxzIiBBbGlhcz0i5qih5Z6L56qX5Y+jIiBJY29uPSJWaXNpYmxlTW9kZWxzIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTAwMyIgQm91bmRzPSIxLDAiIE5hbWU9IlZpc2libGVQYXJhbWV0ZXJzIiBBbGlhcz0i5Y+C5pWw56qX5Y+jIiBJY29uPSJWaXNpYmxlUGFyYW1ldGVycyIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkxMDEiIEJvdW5kcz0iMCwxIiBOYW1lPSJWaXNpYmxlQW5hbEJhc2ljIiBBbGlhcz0i5Z+656GA5L+h5oGvIiBJY29uPSJJbnB1dEJhc2ljIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTEwMiIgQm91bmRzPSIxLDEiIE5hbWU9IlZpc2libGVBbmFsUFZUIiBBbGlhcz0iUFZU5pWw5o2uIiBJY29uPSJJbnB1dEZsdWlkIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTEwMyIgQm91bmRzPSIwLDIiIE5hbWU9IlZpc2libGVBbmFsRGlmZiIgQWxpYXM9IkRJRkbmlbDmja4iIEljb249IklucHV0Rmx1aWQiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI5MTA0IiBCb3VuZHM9IjEsMiIgTmFtZT0iVmlzaWJsZUFuYWxQc2V1IiBBbGlhcz0i5ouf5Y6L5Yqb5pWw5o2uIiBJY29uPSJJbnB1dEZsdWlkIiAvPg0KICAgICAgICA8L0dyb3VwPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJIZWxwIiBBbGlhcz0i5biu5YqpIj4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjEwMDAyIiBCb3VuZHM9IjAsMCwyLDEiIE5hbWU9IkhlbHAiIEFsaWFzPSLluK7liqkoSCkiIEljb249IkhlbHAiIC8+DQogICAgICAgIDwvR3JvdXA+DQoNCiAgICA8L1RhYj4NCg0KDQogICAgPFRhYiBJRD0iMiIgTmFtZT0iRGF0YU1hbmFnZXIiIEFsaWFzPSLmlbDmja7nrqHnkIYoRCkiID4NCg0KICAgICAgICA8R3JvdXAgTmFtZT0iRGF0YU1hbmFnZXIiIEFsaWFzPSLkupUiPg0KICAgICAgICAgICAgPENtZCBJRD0iMTA5OSIgQm91bmRzPSIwLDAsMiwxIiBOYW1lPSJXZWxsTmV3IiBBbGlhcz0i5paw5bu65LqVKFcpIiBJY29uPSJXZWxsTmV3IiAvPg0KICAgICAgICA8L0dyb3VwPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJEYXRhTWFuYWdlciIgQWxpYXM9IuWfuuehgOaVsOaNriI+DQogICAgICAgICAgICA8Q21kIElEPSIyMDAxIiBCb3VuZHM9IjAsMCwyLDEiIE5hbWU9IkRhdGFXZWxsQmFzaWMiIEFsaWFzPSLkupXln7rnoYDmlbDmja4oQikiIEV4dEluZm89IkJfV0VMTCIgSWNvbj0iQmFzaWNEYXRhIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMjAwMiIgQm91bmRzPSIwLDEsMiwxIiBOYW1lPSJEYXRhTGF5ZXIiIEFsaWFzPSLlnLDotKjliIblsYLmlbDmja4oTCkiIEV4dEluZm89IkJfTEFZRVIiIEljb249IkxheWVyRGF0YSIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjIwMDMiIEJvdW5kcz0iMCwyLDIsMSIgTmFtZT0iRGF0YVJlcyIgQWxpYXM9IuWCqOWxguaVsOaNrihSKSIgRXh0SW5mbz0iUF9EQVRBX1JFUyIgSWNvbj0iUmVzRGF0YSIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjIwMDQiIEJvdW5kcz0iMCwzLDIsMSIgTmFtZT0iRGF0YUZsdSIgQWxpYXM9Iua1geS9k+aAp+i0qOaVsOaNrihGKSIgRXh0SW5mbz0iUF9EQVRBX0ZMVUlEIiBJY29uPSJGbHVpZFByb3BlcnR5IiAvPg0KICAgICAgICA8L0dyb3VwPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJEYXRhTWFuYWdlciIgQWxpYXM9IuWOi+WKm+a1gemHjyI+DQogICAgICAgICAgICA8Q21kIElEPSIyMDA1IiBCb3VuZHM9IjAsMCwyLDEiIE5hbWU9IkRhdGFSYXRlIiBBbGlhcz0i5rWB6YeP5pWw5o2uKFEpIiBFeHRJbmZvPSJQX0RBVEFfR0FVR0VfRiIgSWNvbj0iUmF0ZURhdGEiIC8+DQogICAgICAgICAgICA8Q21kIElEPSIyMDA2IiBCb3VuZHM9IjAsMSwyLDEiIE5hbWU9IkRhdGFQcmUiIEFsaWFzPSLljovlipvmlbDmja4oUCkiIEV4dEluZm89IlBfREFUQV9HQVVHRV9QIiBJY29uPSJQcmVzc3VyZURhdGEiIC8+DQogICAgICAgIDwvR3JvdXA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9IkdYNiIgQWxpYXM9IuW5s+WPsOS6kumAmiI+DQogICAgICAgICAgICA8Q21kIElEPSIyMDA3IiBCb3VuZHM9IjAsMCwyLDEiIE5hbWU9Ikd4NkNvbm5lY3RTZXJ2ZXIiIEFsaWFzPSJHWDbkupLpgJooQykiIEljb249Ikd4NkNvbm5lY3RTZXJ2ZXIiIC8+DQogICAgICAgICAgICA8Q21kIElEPSIyMDA4IiBCb3VuZHM9IjAsMSwyLDEiIE5hbWU9Ikd4NkdldFRhc2tzIiBBbGlhcz0i6I635Y+W5Lu75YqhKEQpIiBJY29uPSJHeDZHZXRUYXNrcyIgIFZpc2libGU9IjAiLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjIwMDkiIEJvdW5kcz0iMCwyLDIsMSIgTmFtZT0iR3g2VXBkYXRlVGFza3MiIEFsaWFzPSLmm7TmlrDnirbmgIEoVSkiIEljb249Ikd4NlVwZGF0ZVRhc2tzIiAgVmlzaWJsZT0iMCIvPg0KICAgICAgICA8L0dyb3VwPg0KDQogICAgPC9UYWI+DQoNCiAgICA8VGFiIElEPSIyMDEiIE5hbWU9IkRhdGFFZGl0IiBBbGlhcz0i5pWw5o2u57yW6L6RKEUpIiA+DQogICAgICAgIDxHcm91cCBOYW1lPSJEYXRhRWRpdCIgQWxpYXM9IuaVsOaNrue8lui+kSI+DQogICAgICAgICAgICA8Q21kIElEPSIzMDAxIiBCb3VuZHM9IjAsMCwyLDEiIE5hbWU9IkFuYWxGbHUiIEFsaWFzPSLmtYHph4/nvJbovpEiIEV4dEluZm89IkYiIE1kaVR5cGU9IkRhdGFFZGl0IiBJY29uPSJSYXRlRGF0YSIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjMwMDIiIEJvdW5kcz0iMCwxLDIsMSIgTmFtZT0iQW5hbFByZXNzIiBBbGlhcz0i5Y6L5Yqb57yW6L6RIiBFeHRJbmZvPSJQIiBNZGlUeXBlPSJEYXRhRWRpdCIgSWNvbj0iUHJlc3N1cmVEYXRhIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMzMwMyIgQm91bmRzPSIwLDIsMiwxIiBOYW1lPSJBbmFsUHJlQ29uIiBBbGlhcz0i5Y6L5Yqb5oqY566XIiBFeHRJbmZvPSJQIiBNZGlUeXBlPSJEYXRhRWRpdCIgSWNvbj0iQW5hbFByZUNvbiIgLz4NCiAgICAgICAgPC9Hcm91cD4NCiAgICA8L1RhYj4NCg0KICAgIDxUYWIgSUQ9IjMiIE5hbWU9IkFuYWx5dGljYWxUZXN0IiBBbGlhcz0i5aSE55CG6Kej6YeKKEEpIiA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9IkFuYWxFZGl0IiBBbGlhcz0i5YiG5p6Q566h55CGIj4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjMwMDYiIEJvdW5kcz0iMCwwIiBOYW1lPSJBbmFsTmV3IiBBbGlhcz0i5paw5bu65YiG5p6QIiBJY29uPSJKb2JOZXciIC8+DQogICAgICAgICAgICA8Q21kIElEPSIzMDA3IiBCb3VuZHM9IjEsMCIgTmFtZT0iQW5hbEVkaXQiIEFsaWFzPSLliIbmnpDnrqHnkIYiIEljb249IkpvYkVkaXQiIC8+DQogICAgICAgIDwvR3JvdXA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9IlNlZ0FuYWwiIEFsaWFzPSLmtYHliqjmrrXliIbmnpAiPg0KICAgICAgICAgICAgPENtZCBJRD0iMzAwMyIgQm91bmRzPSIwLDAsMiwxIiBOYW1lPSJBbmFsUEYiIEFsaWFzPSLmtYHliqjmrrXpgInmi6kiIEV4dEluZm89IlBGIiBJY29uPSJQRiIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjMwMDQiIEJvdW5kcz0iMCwxLDIsMSIgTmFtZT0iQW5hbEZsb3dTZWciIEFsaWFzPSLmtYHliqjmrrXliIbmnpAiIEljb249IkZsb3dQZXJpb2QiIC8+DQogICAgICAgICAgICA8Q21kIElEPSIzMDA1IiBCb3VuZHM9IjAsMiwyLDEiIE5hbWU9IkFuYWxPdGhlcnMiIEFsaWFzPSLnibnlvoHnur/liIbmnpAiIFR5cGU9IjEiICBWaXNpYmxlPSIwIiBFeHROYW1lcz0iQ2hhcnRUO0NoYXJ0U3FydFQ7Q2hhcnQyNVQ7Q2hhcnQ1VCIgRXh0SW5mbz0iQ2hhcnQgVDtDaGFydCBTcXJ0KFQpO0NoYXJ0IDAuMjVUO0NoYXJ0IC0wLjVUIiBJY29uPSJBc3Npc0FuYWwiIC8+DQogICAgICAgICAgICA8Q21kIElEPSIzMDEwIiBCb3VuZHM9IjAsMywyLDEiIE5hbWU9IkFuYWxXbmRNIiBBbGlhcz0i5rWB5Yqo5q6156qX5Y+jIiBUeXBlPSIxIiBJY29uPSJBbmFsV25kTSIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjMwMDkiIEJvdW5kcz0iMCw0LDIsMSIgTmFtZT0iQW5hbERpc3RyaSIgQWxpYXM9IuWIhuW4g+WbviIgVHlwZT0iMSIgRXh0TmFtZXM9IkNoYXJ0RGVuO0NoYXJ0VmlzIiBFeHRJbmZvPSLmtZPluqbliIbluIPlm7476buP5bqm5YiG5biD5Zu+IiBJY29uPSJBbmFsRGlzdHJpIiAvPg0KICAgICAgICA8L0dyb3VwPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJEYXRhRml0IiBBbGlhcz0i6Kej6YeK5ouf5ZCIIj4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjMxMDUiIEJvdW5kcz0iMCwwLDIsMSIgTmFtZT0iRGVjb252b2x2IiBBbGlhcz0i5Y+N6KS256evKERlYnVnKSIgSWNvbj0iRGVjb252b2x2IiAvPg0KDQogICAgICAgICAgICA8Q21kIElEPSIzMTAxIiBCb3VuZHM9IjAsMSwyLDEiIE5hbWU9IkZpdE1vZGVsIiBBbGlhcz0i6Kej5p6Q6KejIiBJY29uPSJGaXRNb2RlbCIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjMxMDQiIEJvdW5kcz0iMCwyLDIsMSIgTmFtZT0ibm1GaXRNb2RlbCIgQWxpYXM9IuaVsOWAvOinoyIgSWNvbj0iRml0TW9kZWwiIC8+DQogICAgICAgICAgICA8Q21kIElEPSIzMTAyIiBCb3VuZHM9IjAsMywyLDEiIE5hbWU9IkF1dG9GaXQiIEFsaWFzPSLoh6rliqjmi5/lkIgiIEljb249IkF1dG9GaXQiIC8+DQogICAgICAgICAgICA8Q21kIElEPSIzMTAzIiBCb3VuZHM9IjAsNCwyLDEiIE5hbWU9IlBsYXRlRml0IiBBbGlhcz0i5pWP5oSf5oCn5YiG5p6QIiBJY29uPSJQbGF0ZUZpdCIgLz4NCiAgICAgICA8L0dyb3VwPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJBSVRlc3QiIEFsaWFzPSLmmbrog73or5XkupUiPg0KICAgICAgICAgICAgPENtZCBJRD0iMzkwMSIgQm91bmRzPSIwLDAsMiwxIiBOYW1lPSJNb2RlbENsYXNzaWZ5IiBBbGlhcz0i5qih5Z6L6K+G5YirIiBJY29uPSJNb2RlbENsYXNzaWZ5IiAvPg0KICAgICAgICA8L0dyb3VwPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJSZWxhdGl2ZVRvb2wiIEFsaWFzPSLnm7jlhbPlt6XlhbciPg0KICAgICAgICAgICAgPENtZCBJRD0iMzIwMSIgQm91bmRzPSIwLDAsMiwxIiBOYW1lPSJUaW1lIiBBbGlhcz0i5pe26Ze0IiBJY29uPSJUaW1lIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMzIwMiIgQm91bmRzPSIwLDEiIE5hbWU9IlNob3dNb2RlbENoYXJ0cyIgQWxpYXM9IuaooeWei+ekuuaEjyIgSWNvbj0iU2hvd01vZGVsQ2hhcnRzIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMzIwNCIgQm91bmRzPSIxLDEiIE5hbWU9IlNhdmVBc01vZGVsU2tldGNoIiBBbGlhcz0i5a2Y5Li656S65oSPIiBJY29uPSJTYXZlQXNNb2RlbFNrZXRjaCIgLz4NCg0KICAgICAgIDwvR3JvdXA+DQoNCjwhLS0gICAgICAgICAgICAgICAgICAgIDxDbWQgSUQ9IjMyMDMiIEJvdW5kcz0iMCwxIiBOYW1lPSJTaG93TW9kZWxTa2V0Y2giIEFsaWFzPSLnkIborroiIEljb249IlNob3dNb2RlbFNrZXRjaCIgLz48R3JvdXAgTmFtZT0iVG9vbFMiIEFsaWFzPSLmianlsZXlip/og70iPg0KICAgICAgICAgICAgPENtZCBJRD0iOTgwMSIgQm91bmRzPSIwLDAsMiwxIiBOYW1lPSJGbG93VG9TIiBBbGlhcz0i5rWB6YeP5Y+Y6KGo55quIiBJY29uPSJGbG93VG9TIiBWaXNpYmxlPSIwIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTIwMSIgQm91bmRzPSIwLDEsMiwxIiBOYW1lPSJNaXhWaXNjb3NpdHkiIEFsaWFzPSLmt7flkIjpu4/luqYiIEljb249Ik1peFZpc2Nvc2l0eSIgVmlzaWJsZT0iMCIgLz4NCiAgICAgICA8L0dyb3VwPi0tPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJKb2JzIiBBbGlhcz0i5oiQ5p6c566h55CGIj4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjEwMDgiIEJvdW5kcz0iMCwwIiBOYW1lPSJSc3RMb2FkIiBBbGlhcz0i5Yqg6L295oiQ5p6cIiBJY29uPSJMb2FkSm9icyIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjEwMDkiIEJvdW5kcz0iMSwwIiBOYW1lPSJSc3RTYXZlIiBUeXBlPSIxIiBFeHROYW1lcz0iUnN0U2F2ZUN1cjtSc3RTYXZlQWxsIiBFeHRJbmZvPSLkv53lrZjlvZPliY3miJDmnpw75L+d5a2Y5omA5pyJ5oiQ5p6cIiBBbGlhcz0i5L+d5a2Y5oiQ5p6cIiBJY29uPSJTYXZlSm9icyIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjEwMTEiIEJvdW5kcz0iMCwxLDIsMSIgTmFtZT0iVG9OdW1lcmljYWwiIEFsaWFzPSJUby3mlbDlgLwiIEljb249IkxvYWRKb2JzIiBWaXNpYmxlPSIwIiAvPg0KICAgICAgICA8L0dyb3VwPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJXaW5kb3ciIEFsaWFzPSLnqpflj6PmmL7npLoiPg0KICAgICAgICAgICAgPENtZCBJRD0iOTAwMiIgQm91bmRzPSIwLDAiIE5hbWU9IlZpc2libGVNb2RlbHMiIEFsaWFzPSLmqKHlnovnqpflj6MiIEljb249IlZpc2libGVNb2RlbHMiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI5MDAzIiBCb3VuZHM9IjEsMCIgTmFtZT0iVmlzaWJsZVBhcmFtZXRlcnMiIEFsaWFzPSLlj4LmlbDnqpflj6MiIEljb249IlZpc2libGVQYXJhbWV0ZXJzIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTEwMSIgQm91bmRzPSIwLDEiIE5hbWU9IlZpc2libGVBbmFsQmFzaWMiIEFsaWFzPSLln7rnoYDkv6Hmga8iIEljb249IklucHV0QmFzaWMiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI5MTAyIiBCb3VuZHM9IjEsMSIgTmFtZT0iVmlzaWJsZUFuYWxQVlQiIEFsaWFzPSJQVlTmlbDmja4iIEljb249IklucHV0Rmx1aWQiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI5MTAzIiBCb3VuZHM9IjAsMiIgTmFtZT0iVmlzaWJsZUFuYWxEaWZmIiBBbGlhcz0iRElGRuaVsOaNriIgSWNvbj0iSW5wdXRGbHVpZCIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkxMDQiIEJvdW5kcz0iMSwyIiBOYW1lPSJWaXNpYmxlQW5hbFBzZXUiIEFsaWFzPSLmi5/ljovlipvmlbDmja4iIEljb249IklucHV0Rmx1aWQiIC8+DQogICAgICAgIDwvR3JvdXA+DQogICAgPC9UYWI+DQoNCiAgICA8VGFiIElEPSI1IiBOYW1lPSJOdW1lcmljYWxUZXN0IiBBbGlhcz0i5pWw5YC85bu65qihKE4pIiA+DQogICAgICAgIDxHcm91cCBOYW1lPSJObU1hbmFnZXIiIEFsaWFzPSLliIbmnpDnrqHnkIYiIFZpc2libGU9IjAiPg0KICAgICAgICAgICAgPENtZCBJRD0iNTAwMSIgQm91bmRzPSIwLDAsMiwxIiBOYW1lPSJBbmFsTmV3IiBBbGlhcz0i5Li05pe25rWL6K+VMSIgSWNvbj0iUHJlcGFyZUdyaWQiIFZpc2libGU9IjAiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI1MDAyIiBCb3VuZHM9IjAsMSwyLDEiIE5hbWU9IlByb3BlcnR5TG9hZCIgQWxpYXM9IuS4tOaXtua1i+ivlTIiIEljb249IlByZXBhcmVHcmlkIiAgVmlzaWJsZT0iMCIvPg0KICAgICAgICA8L0dyb3VwPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJObUFuYWxDaGFuZ2UiIEFsaWFzPSLliIbmnpDliIfmjaIiPg0KICAgICAgICAgICAgPENtZCBJRD0iNTEzMCIgQm91bmRzPSIwLDAiIE5hbWU9Ik5tQW5hbENoYW5nZSIgQWxpYXM9IuWIhuaekOWIh+aNoiIgSWNvbj0iSm9iRWRpdCIgLz4NCiAgICAgICA8L0dyb3VwPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJOdEluaXQiIEFsaWFzPSLmqKHlnovlh6DkvZXlr7nosaEiPg0KICAgICAgICAgICAgPENtZCBJRD0iNTExOCIgQm91bmRzPSIwLDAsMiwxIiBOYW1lPSJObU1hcCIgQWxpYXM9Ik1hcCIgSWNvbj0iTm1JbWFnZSIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjUxMTkiIEJvdW5kcz0iMCwxLDIsMSIgTmFtZT0iTm1VbmxvY2tlZCIgQWxpYXM9IumUgeWumiIgSWNvbj0iTm1VbmxvY2tlZCIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjUxMDIiIEJvdW5kcz0iMCwyLDIsMSIgTmFtZT0iTm1JbWFnZSIgQWxpYXM9IuayueiXj+WcsOWbviIgSWNvbj0iTm1JbWFnZSIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjUxMjAiIEJvdW5kcz0iMCwzLDIsMSIgTmFtZT0iTm1NZWFzdXJlIiBBbGlhcz0i5q+U5L6L5bC6IiBJY29uPSJObU1lYXN1cmUiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI1MTAzIiBCb3VuZHM9IjAsNCwyLDEiIE5hbWU9Ik5tUG9seWdvbiIgQWxpYXM9IuWkmui+ueW9oui+ueeVjCIgSWNvbj0iTm1Qb2x5Z29uIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iNTEwNCIgQm91bmRzPSIwLDUiIE5hbWU9Ik5tUG9seWdvbiIgQWxpYXM9IuefqeW9oui+ueeVjCIgSWNvbj0iTm1SZWN0YW5nbGUiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI1MTA1IiBCb3VuZHM9IjEsNSIgTmFtZT0iTm1Qb2x5Z29uIiBBbGlhcz0i5ZyG5b2i6L6555WMIiBJY29uPSJObVJvdW5kIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iNTEwNiIgQm91bmRzPSIwLDYsMiwxIiBOYW1lPSJObUZhdWx0IiBBbGlhcz0i5pat5bGCIiBJY29uPSJObUZhdWx0IiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iNTEwNyIgQm91bmRzPSIwLDciIE5hbWU9Ik5tV2VsbCIgQWxpYXM9IumAieaLqeS6lSIgSWNvbj0iTm1XZWxsIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iNTEwOCIgQm91bmRzPSIxLDciIE5hbWU9Ik5tV2VsbCIgQWxpYXM9IuaWsOW7uuS6lSIgSWNvbj0iTm1XZWxsIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iNTEwOSIgQm91bmRzPSIwLDgsMiwxIiBOYW1lPSJObUZhdWx0IiBBbGlhcz0i6KOC57ydIiBJY29uPSJObUZhdWx0IiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iNTExMCIgQm91bmRzPSIwLDkiIE5hbWU9Ik5tTGltaXQiIEFsaWFzPSLljLrln58iIEljb249Ik5tTGltaXQiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI1MTExIiBCb3VuZHM9IjEsOSIgTmFtZT0iTm1SZWdpb24iIEFsaWFzPSLmoIforrDljLrln58iIEljb249Ik5tUmVnaW9uIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iNTEyMSIgQm91bmRzPSIwLDEwLDIsMSIgTmFtZT0iTm1EZWxldGUiIEFsaWFzPSLliKDpmaQiIEljb249Ik5tRGVsZXRlIiAvPg0KICAgICAgIDwvR3JvdXA+DQoNCiAgICAgICA8R3JvdXAgTmFtZT0iTnRSZXNlcnZvaXIiIEFsaWFzPSLlgqjlsYLnibnlvoEiPg0KICAgICAgICAgICAgPENtZCBJRD0iNTExMiIgQm91bmRzPSIwLDAsMiwxIiBOYW1lPSJObUdlb21ldHJ5IiBBbGlhcz0i5YiG5bGCIiBJY29uPSJObUdlb21ldHJ5IiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iNTExMyIgQm91bmRzPSIwLDEsMiwxIiBOYW1lPSJObVByb3BlcnRpZXMiIEFsaWFzPSLlgqjlsYLnibnmgKciIEljb249Ik5tUHJvcGVydGllcyIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjUxMjIiIEJvdW5kcz0iMCwyLDIsMSIgTmFtZT0iTm1ERk4iIEFsaWFzPSJERk4iIEljb249Ik5tREZOIiAvPg0KICAgICAgIDwvR3JvdXA+DQoNCiAgICAgICA8R3JvdXAgTmFtZT0iTnRNb2RlbCIgQWxpYXM9IuaooeWei+eUn+aIkCI+DQogICAgICAgICAgICAgPENtZCBJRD0iNTExNCIgQm91bmRzPSIwLDAsMiwxIiBOYW1lPSJObUdyaWQiIEFsaWFzPSLnvZHmoLzliJLliIYiIEljb249Ik5tR3JpZCIgLz4NCiAgICAgICAgICAgICA8Q21kIElEPSI1MTE1IiBCb3VuZHM9IjAsMSwyLDEiIE5hbWU9Ik5tQ2FjdWxhdGlvbiIgQWxpYXM9Iuiuoeeul+axguinoyIgSWNvbj0iVGltZSIgLz4NCiAgICAgICAgICAgICA8IS0tDQogICAgICAgICAgICAgPENtZCBJRD0iNTExNiIgQm91bmRzPSIwLDIsMiwxIiBOYW1lPSJObUJhY2siIEFsaWFzPSLlkI7lpITnkIYiIEljb249IlRpbWUiIC8+DQogICAgICAgICAgICAgPENtZCBJRD0iNTExNyIgQm91bmRzPSIwLDMsMiwxIiBOYW1lPSJObVJlc3VsdCIgQWxpYXM9Iue7k+aenCIgSWNvbj0iRmxvd1BlcmlvZCIgLz4NCiAgICAgICAgICAgICAtLT4NCiAgICAgICA8L0dyb3VwPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJOdFRvb2xzIiBBbGlhcz0i5bel5YW3Ij4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjUxMjciIEJvdW5kcz0iMCwwIiBOYW1lPSJObUdlb1JlZmVyZW5jZSIgQWxpYXM9IuaooeWei+WPguiAg+eCueiuvue9riIgSWNvbj0iTm1HZW9SZWZlcmVuY2UiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI1MTI4IiBCb3VuZHM9IjEsMCIgTmFtZT0iTm1Qb2ludGVyUG9zaXRpb24iIEFsaWFzPSLmqKHlnovkvY3nva7mmL7npLoiIEljb249Ik5tUG9pbnRlclBvc2l0aW9uIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iNTEyOSIgQm91bmRzPSIwLDEsMiwxIiBOYW1lPSJObU1lYXN1cmUiIEFsaWFzPSLmqKHlnovlsLrlr7jmtYvph48iIEljb249Ik5tTWVhc3VyZSIgLz4NCiAgICAgICA8L0dyb3VwPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJOdERpc3BsYXkiIEFsaWFzPSLmmL7npLoiPg0KICAgICAgICAgICAgPENtZCBJRD0iNTEyMyIgQm91bmRzPSIwLDAsMiwxIiBOYW1lPSJObVNob3ciIEFsaWFzPSLmmL7npLoiIEljb249Ik5tU2hvdyIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjUxMjQiIEJvdW5kcz0iMCwxLDIsMSIgTmFtZT0iTm1QcmludFByZXZpZXciIEFsaWFzPSLmiZPljbDpooTop4giIEljb249Ik5tUHJpbnRQcmV2aWV3IiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iNTEyNSIgQm91bmRzPSIwLDIsMiwxIiBOYW1lPSJObVByaW50IiBBbGlhcz0i5omT5Y2wIiBJY29uPSJObVByaW50IiAvPg0KICAgICAgIDwvR3JvdXA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9IldpbmRvdyIgQWxpYXM9Iueql+WPo+aYvuekuiIgIFZpc2libGU9IjAiPg0KICAgICAgICAgICAgPENtZCBJRD0iOTAwMiIgQm91bmRzPSIwLDAiIE5hbWU9IlZpc2libGVNb2RlbHMiIEFsaWFzPSLmqKHlnovnqpflj6MiIEljb249IlZpc2libGVNb2RlbHMiICBWaXNpYmxlPSIwIi8+DQogICAgICAgICAgICA8Q21kIElEPSI5MDAzIiBCb3VuZHM9IjEsMCIgTmFtZT0iVmlzaWJsZVBhcmFtZXRlcnMiIEFsaWFzPSLlj4LmlbDnqpflj6MiIEljb249IlZpc2libGVQYXJhbWV0ZXJzIiAgVmlzaWJsZT0iMCIvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTEwMSIgQm91bmRzPSIwLDEiIE5hbWU9IlZpc2libGVBbmFsQmFzaWMiIEFsaWFzPSLln7rnoYDkv6Hmga8iIEljb249IklucHV0QmFzaWMiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI5MTAyIiBCb3VuZHM9IjEsMSIgTmFtZT0iVmlzaWJsZUFuYWxQVlQiIEFsaWFzPSJQVlTmlbDmja4iIEljb249IklucHV0Rmx1aWQiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI5MTAzIiBCb3VuZHM9IjAsMiIgTmFtZT0iVmlzaWJsZUFuYWxEaWZmIiBBbGlhcz0iRElGRuaVsOaNriIgSWNvbj0iSW5wdXRGbHVpZCIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkxMDQiIEJvdW5kcz0iMSwyIiBOYW1lPSJWaXNpYmxlQW5hbFBzZXUiIEFsaWFzPSLmi5/ljovlipvmlbDmja4iIEljb249IklucHV0Rmx1aWQiIC8+DQogICAgICAgIDwvR3JvdXA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9Ik5tRGVidWciIEFsaWFzPSLmoYbmnrbmtYvor5UoRGVidWcpIj4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjU5OTkiIEJvdW5kcz0iMCwwLDIsMSIgTmFtZT0iTm1EZWJ1ZyIgQWxpYXM9IuahhuaetuS7o+eggeiwg+ivlSIgSWNvbj0iUHJlcGFyZUdyaWQiIC8+DQogICAgICAgIDwvR3JvdXA+DQoNCg0KICAgIDwvVGFiPg0KDQogICAgPFRhYiBJRD0iNCIgTmFtZT0iTWluaUZyYWMiIEFsaWFzPSLlsI/lnovljovoo4IoRikoRGVidWcpIiA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9IkFuYWxFZGl0IiBBbGlhcz0i5YiG5p6Q566h55CGIj4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjMwMDYiIEJvdW5kcz0iMCwwIiBOYW1lPSJBbmFsTmV3IiBBbGlhcz0i5paw5bu65YiG5p6QIiBJY29uPSJKb2JOZXciIC8+DQogICAgICAgICAgICA8Q21kIElEPSIzMDA3IiBCb3VuZHM9IjEsMCIgTmFtZT0iQW5hbEVkaXQiIEFsaWFzPSLliIbmnpDnrqHnkIYiIEljb249IkpvYkVkaXQiIC8+DQogICAgICAgIDwvR3JvdXA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9IlBBIiBBbGlhcz0i5Y6L6ZmN5YiG5p6QIj4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjQwMDIiIEJvdW5kcz0iMCwwLDMsMSIgTmFtZT0iTWluaUZyQW5hbFBBIiBBbGlhcz0i5Y6L6ZmN5YeG5aSHIiBFeHRJbmZvPSJQRiIgSWNvbj0iUEYiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI0MDAzIiBCb3VuZHM9IjAsMSwzLDEiIE5hbWU9Ik1pbmlGclBBIiBBbGlhcz0i5Y6L6ZmN5YiG5p6QIiBJY29uPSJGbG93UGVyaW9kIiAvPg0KDQogICAgICAgICAgICA8Q21kIElEPSI0MDA0IiBCb3VuZHM9IjAsMiwzLDEiIE5hbWU9IkNhbFN1ZGRlblN0b3BQIiBBbGlhcz0i556s5pe25YGc5rO15Y6L5YqbIiBJY29uPSJSdW5FeCIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjQwMDUiIEJvdW5kcz0iMCwzIiBOYW1lPSJDYWxHRnVuY3Rpb24iIEFsaWFzPSJH5Ye95pWwIiBJY29uPSJSdW5PdGhlciIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjQwMDYiIEJvdW5kcz0iMSwzIiBOYW1lPSJDYWxTcXJ0VCIgQWxpYXM9IuaXtumXtOW5s+aWueaguSIgSWNvbj0iUnVuT3RoZXIiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI0MDA3IiBCb3VuZHM9IjIsMyIgTmFtZT0iQ2FsTG9nTG9nIiBBbGlhcz0i5Y+M5a+55pWwIiBJY29uPSJSdW5PdGhlciIgLz4NCiAgICAgICAgPC9Hcm91cD4NCg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJGQSIgQWxpYXM9IuaOkumHj+WIhuaekCI+DQogICAgICAgICAgICA8Q21kIElEPSI0MTAyIiBCb3VuZHM9IjAsMCwyLDEiIE5hbWU9Ik1pbmlGckFuYWxGQSIgQWxpYXM9IuaOkumHj+WHhuWkhyIgRXh0SW5mbz0iSVBSIiBJY29uPSJNaW5pRnJBbmFsRkEiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI0MTAzIiBCb3VuZHM9IjAsMSIgTmFtZT0iTWluaUZyRkFVcCIgQWxpYXM9IumYtuair+WNhyIgSWNvbj0iU3RlcFVwIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iNDEwNCIgQm91bmRzPSIxLDEiIE5hbWU9Ik1pbmlGckZBRG93biIgQWxpYXM9IumYtuair+mZjSIgSWNvbj0iU3RlcERvd24iIC8+DQogICAgICAgPC9Hcm91cD4NCg0KICAgICAgICA8R3JvdXAgTmFtZT0iSm9icyIgQWxpYXM9IuaIkOaenOeuoeeQhiIgIFZpc2libGU9IjAiPg0KICAgICAgICAgICAgPENtZCBJRD0iMTAwOCIgQm91bmRzPSIwLDAiIE5hbWU9IlJzdExvYWQiIEFsaWFzPSLliqDovb3miJDmnpwiIEljb249IkxvYWRKb2JzIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMTAwOSIgQm91bmRzPSIxLDAiIE5hbWU9IlJzdFNhdmUiIFR5cGU9IjEiIEV4dE5hbWVzPSJSc3RTYXZlQ3VyO1JzdFNhdmVBbGwiIEV4dEluZm89IuS/neWtmOW9k+WJjeaIkOaenDvkv53lrZjmiYDmnInmiJDmnpwiIEFsaWFzPSLkv53lrZjmiJDmnpwiIEljb249IlNhdmVKb2JzIiAvPg0KICAgICAgICA8L0dyb3VwPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJXaW5kb3ciIEFsaWFzPSLnqpflj6PmmL7npLoiICBWaXNpYmxlPSIwIj4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkwMDIiIEJvdW5kcz0iMCwwIiBOYW1lPSJWaXNpYmxlTW9kZWxzIiBBbGlhcz0i5qih5Z6L56qX5Y+jIiBJY29uPSJWaXNpYmxlTW9kZWxzIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTAwMyIgQm91bmRzPSIxLDAiIE5hbWU9IlZpc2libGVQYXJhbWV0ZXJzIiBBbGlhcz0i5Y+C5pWw56qX5Y+jIiBJY29uPSJWaXNpYmxlUGFyYW1ldGVycyIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkxMDEiIEJvdW5kcz0iMCwxIiBOYW1lPSJWaXNpYmxlQW5hbEJhc2ljIiBBbGlhcz0i5Z+656GA5L+h5oGvIiBJY29uPSJJbnB1dEJhc2ljIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTEwMiIgQm91bmRzPSIxLDEiIE5hbWU9IlZpc2libGVBbmFsUFZUIiBBbGlhcz0iUFZU5pWw5o2uIiBJY29uPSJJbnB1dEZsdWlkIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTEwMyIgQm91bmRzPSIwLDIiIE5hbWU9IlZpc2libGVBbmFsRGlmZiIgQWxpYXM9IkRJRkbmlbDmja4iIEljb249IklucHV0Rmx1aWQiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI5MTA0IiBCb3VuZHM9IjEsMiIgTmFtZT0iVmlzaWJsZUFuYWxQc2V1IiBBbGlhcz0i5ouf5Y6L5Yqb5pWw5o2uIiBJY29uPSJJbnB1dEZsdWlkIiAvPg0KICAgICAgICA8L0dyb3VwPg0KDQogICAgPC9UYWI+DQoNCiAgICA8VGFiIElEPSI0MDEiIE5hbWU9IklQUiIgQWxpYXM9IuS6p+iDveivleS6lShQKSIgPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJBbmFsRWRpdCIgQWxpYXM9IuWIhuaekOeuoeeQhiI+DQogICAgICAgICAgICA8Q21kIElEPSIzMDA2IiBCb3VuZHM9IjAsMCIgTmFtZT0iQW5hbE5ldyIgQWxpYXM9IuaWsOW7uuWIhuaekCIgSWNvbj0iSm9iTmV3IiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMzAwNyIgQm91bmRzPSIxLDAiIE5hbWU9IkFuYWxFZGl0IiBBbGlhcz0i5YiG5p6Q566h55CGIiBJY29uPSJKb2JFZGl0IiAvPg0KICAgICAgICA8L0dyb3VwPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJJUFIiIEFsaWFzPSJJUFLlhYjliY3lj4LogIMoRGVidWcpIj4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjYwMDIiIEJvdW5kcz0iMCwwLDIsMSIgTmFtZT0iSVBSQW5hbCIgQWxpYXM9IklQUuWHhuWkhyIgRXh0SW5mbz0iSVBSIiBJY29uPSJJUFJBbmFsIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iNjAwMyIgQm91bmRzPSIwLDEsMiwxIiBOYW1lPSJJUFJDYWwiIEFsaWFzPSJJUFLorqHnrpciIEljb249IklQUkNhbCIgLz4NCiAgICAgICAgPC9Hcm91cD4NCg0KICAgICAgICA8R3JvdXAgTmFtZT0iV2R0RGF0YVByZXByb2Nlc3MiIEFsaWFzPSLmlbDmja7pooTlpITnkIYiIFZpc2libGU9IjAiPg0KICAgICAgICAgICAgPENtZCBJRD0iNjEwMSIgQm91bmRzPSIwLDAsMiwxIiBOYW1lPSJXZHREYXRhQXNzbiIgQWxpYXM9IuaVsOaNruW9kuS4gOWMliIgRXh0SW5mbz0iSVBSIiBJY29uPSJJUFJBbmFsIiAgVmlzaWJsZT0iMCIvPg0KICAgICAgICAgICAgPENtZCBJRD0iNjEwMiIgQm91bmRzPSIwLDEsMiwxIiBOYW1lPSJXZHRPdGhlciIgQWxpYXM9IuWFtuWugyIgSWNvbj0iV2R0T3RoZXIiIFZpc2libGU9IjAiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI2MTAzIiBCb3VuZHM9IjAsMywyLDEiIE5hbWU9IldkdFdNRiIgQWxpYXM9IuS6leetkuWkmuebuOa1gSIgSWNvbj0iV2R0V01GIiAgVmlzaWJsZT0iMCIvPg0KICAgICAgICAgICAgPENtZCBJRD0iNjEwNCIgQm91bmRzPSIwLDQsMiwxIiBOYW1lPSJXZHRDaG9rZSIgQWxpYXM9IuWYtOa1gSIgSWNvbj0iV2R0Q2hva2UiICBWaXNpYmxlPSIwIi8+DQogICAgICAgIDwvR3JvdXA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9IklQUiIgQWxpYXM9IuS6p+iDveWIhuaekCI+DQogICAgICAgICAgICA8Q21kIElEPSI2MjAxIiBCb3VuZHM9IjAsMCwyLDEiIE5hbWU9IldkdElQUkNhbCIgQWxpYXM9IuWCqOWxguS6p+iDveiuoeeulyIgSWNvbj0iSVBSQ2FsIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iNjIwMiIgQm91bmRzPSIwLDEsMiwxIiBOYW1lPSJXZWxsUGR0eSIgQWxpYXM9IuS4gOS9k+WMluS6p+iDvSIgSWNvbj0iV2VsbFBkdHkiICBWaXNpYmxlPSIwIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iNjIwMyIgQm91bmRzPSIwLDIsMiwxIiBOYW1lPSJXZHRJUFJFeHQiIEFsaWFzPSLkuqfog73or5XkupVb5omp5bGVXSIgSWNvbj0iSVBSRXh0Ii8+DQogICAgICAgICAgICA8Q21kIElEPSI2MjA0IiBCb3VuZHM9IjAsMywyLDEiIE5hbWU9IldkdElQUkFuYWwiIEFsaWFzPSLlgqjlsYLkuqfog73liIbmnpAiIEljb249IklQUkFuYWwiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI2MjA1IiBCb3VuZHM9IjAsNCwyLDEiIE5hbWU9IldlbGxJbnRlZ0FuYWwiIEFsaWFzPSLnu7zlkIjliIbmnpAiIEljb249IldlbGxJbnRlZ0FuYWwiIFZpc2libGU9IjAiIC8+DQogICAgICAgIDwvR3JvdXA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9IklQUiIgQWxpYXM9IuS6p+iDveiuoeeulyI+DQogICAgICAgICAgICA8Q21kIElEPSI2MzAxIiBCb3VuZHM9IjAsMCwyLDEiIE5hbWU9IldkdENhbCIgQWxpYXM9IuiuoeeulyIgSWNvbj0iUnVuRXgiIC8+DQogICAgICAgIDwvR3JvdXA+DQoNCg0KICAgICAgICA8R3JvdXAgTmFtZT0iSm9icyIgQWxpYXM9IuaIkOaenOeuoeeQhiI+DQogICAgICAgICAgICA8Q21kIElEPSIxMDA4IiBCb3VuZHM9IjAsMCIgTmFtZT0iUnN0TG9hZCIgQWxpYXM9IuWKoOi9veaIkOaenCIgSWNvbj0iTG9hZEpvYnMiIC8+DQogICAgICAgICAgICA8Q21kIElEPSIxMDA5IiBCb3VuZHM9IjEsMCIgTmFtZT0iUnN0U2F2ZSIgVHlwZT0iMSIgRXh0TmFtZXM9IlJzdFNhdmVDdXI7UnN0U2F2ZUFsbCIgRXh0SW5mbz0i5L+d5a2Y5b2T5YmN5oiQ5p6cO+S/neWtmOaJgOacieaIkOaenCIgQWxpYXM9IuS/neWtmOaIkOaenCIgSWNvbj0iU2F2ZUpvYnMiIC8+DQogICAgICAgIDwvR3JvdXA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9IldpbmRvdyIgQWxpYXM9Iueql+WPo+aYvuekuiI+DQogICAgICAgICAgICA8Q21kIElEPSI5MDAyIiBCb3VuZHM9IjAsMCIgTmFtZT0iVmlzaWJsZU1vZGVscyIgQWxpYXM9IuaooeWei+eql+WPoyIgSWNvbj0iVmlzaWJsZU1vZGVscyIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkwMDMiIEJvdW5kcz0iMSwwIiBOYW1lPSJWaXNpYmxlUGFyYW1ldGVycyIgQWxpYXM9IuWPguaVsOeql+WPoyIgSWNvbj0iVmlzaWJsZVBhcmFtZXRlcnMiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI5MTAxIiBCb3VuZHM9IjAsMSIgTmFtZT0iVmlzaWJsZUFuYWxCYXNpYyIgQWxpYXM9IuWfuuehgOS/oeaBryIgSWNvbj0iSW5wdXRCYXNpYyIgICBWaXNpYmxlPSIwIi8+DQogICAgICAgICAgICA8Q21kIElEPSI5MTAyIiBCb3VuZHM9IjAsMSIgTmFtZT0iVmlzaWJsZUFuYWxQVlQiIEFsaWFzPSJQVlTmlbDmja4iIEljb249IklucHV0Rmx1aWQiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI5MTAzIiBCb3VuZHM9IjAsMiIgTmFtZT0iVmlzaWJsZUFuYWxEaWZmIiBBbGlhcz0iRElGRuaVsOaNriIgSWNvbj0iSW5wdXRGbHVpZCIgICBWaXNpYmxlPSIwIi8+DQogICAgICAgICAgICA8Q21kIElEPSI5MTA0IiBCb3VuZHM9IjEsMSIgTmFtZT0iVmlzaWJsZUFuYWxQc2V1IiBBbGlhcz0i5ouf5Y6L5Yqb5pWw5o2uIiBJY29uPSJJbnB1dEZsdWlkIiAvPg0KICAgICAgICA8L0dyb3VwPg0KDQoNCiAgICA8L1RhYj4NCg0KICAgIDxUYWIgSUQ9IjYiIE5hbWU9IkFkdmFuY2VkRnVuY3Rpb24iIEFsaWFzPSLpq5jnuqflip/og70oWCkiID4NCg0KICAgICAgICA8R3JvdXAgTmFtZT0iRGVzaWduIiBBbGlhcz0i6K+V5LqV6K6+6K6hIj4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjYwMDEiIEJvdW5kcz0iMCwwLDIsMSIgTmFtZT0iVGVzdERlc2lnbiIgQWxpYXM9IuivleS6leiuvuiuoSIgSWNvbj0iVGVzdERlc2lnbiIgRXh0SW5mbz0iUEYiICAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMzAwNCIgQm91bmRzPSIwLDEsMiwxIiBOYW1lPSJBbmFsRmxvd1NlZyIgQWxpYXM9Iua1geWKqOauteWIhuaekCIgSWNvbj0iRmxvd1BlcmlvZCIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjMwMDUiIEJvdW5kcz0iMCwyLDIsMSIgTmFtZT0iQW5hbE90aGVycyIgQWxpYXM9IueJueW+geauteWIhuaekCIgVHlwZT0iMSIgRXh0TmFtZXM9IkNoYXJ0VDtDaGFydFNxcnRUO0NoYXJ0MjVUO0NoYXJ0NVQiIEV4dEluZm89IkNoYXJ0IFQ7Q2hhcnQgU3FydChUKTtDaGFydCAwLjI1VDtDaGFydCAtMC41VCIgSWNvbj0iQXNzaXNBbmFsIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMzAwOSIgQm91bmRzPSIwLDMsMiwxIiBOYW1lPSJBbmFsRGlzdHJpIiBBbGlhcz0i5YiG5biD5Zu+IiBUeXBlPSIxIiBFeHROYW1lcz0iQ2hhcnREZW47Q2hhcnRWaXMiIEV4dEluZm89Iua1k+W6puWIhuW4g+Wbvjvpu4/luqbliIbluIPlm74iIEljb249IkFuYWxEaXN0cmkiIC8+DQoNCiAgICAgICAgPC9Hcm91cD4NCg0KICAgICAgICA8R3JvdXAgTmFtZT0iRGF0YUZpdCIgQWxpYXM9Iuino+mHiuaLn+WQiCI+DQoNCiAgICAgICAgICAgIDxDbWQgSUQ9IjMxMDUiIEJvdW5kcz0iMCwwLDIsMSIgTmFtZT0iRGVjb252b2x2IiBBbGlhcz0i5Y+N6KS256evIiBJY29uPSJEZWNvbnZvbHYiIFZpc2libGU9IjAiLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjMxMDEiIEJvdW5kcz0iMCwxLDIsMSIgTmFtZT0iRml0TW9kZWwiIEFsaWFzPSLop6PmnpDop6MiIEljb249IkZpdE1vZGVsIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMzEwNCIgQm91bmRzPSIwLDIsMiwxIiBOYW1lPSJubUZpdE1vZGVsIiBBbGlhcz0i5pWw5YC86KejIiBJY29uPSJGaXRNb2RlbCIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjMxMDIiIEJvdW5kcz0iMCwzLDIsMSIgTmFtZT0iQXV0b0ZpdCIgQWxpYXM9IuiHquWKqOaLn+WQiCIgSWNvbj0iQXV0b0ZpdCIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjMxMDMiIEJvdW5kcz0iMCw0LDIsMSIgTmFtZT0iUGxhdGVGaXQiIEFsaWFzPSLmlY/mhJ/mgKfliIbmnpAiIEljb249IlBsYXRlRml0IiAvPg0KICAgICAgIDwvR3JvdXA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9IkFJVGVzdCIgQWxpYXM9IuaZuuiDveivleS6lShEZWJ1ZykiPg0KICAgICAgICAgICAgPENtZCBJRD0iMzkwMSIgQm91bmRzPSIwLDAsMiwxIiBOYW1lPSJNb2RlbENsYXNzaWZ5IiBBbGlhcz0i5qih5Z6L6K+G5YirIiBJY29uPSJNb2RlbENsYXNzaWZ5IiAvPg0KICAgICAgICA8L0dyb3VwPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJSZWxhdGl2ZVRvb2wiIEFsaWFzPSLnm7jlhbPlt6XlhbciIFZpc2libGU9IjAiPg0KICAgICAgICAgICAgPENtZCBJRD0iMzIwMSIgQm91bmRzPSIwLDAiIE5hbWU9IlRpbWUiIEFsaWFzPSLml7bpl7QiIEljb249IlRpbWUiIC8+DQogICAgICAgICAgICA8Q21kIElEPSIzMjAyIiBCb3VuZHM9IjEsMCIgTmFtZT0iU2hvd01vZGVsQ2hhcnRzIiBBbGlhcz0i5qih5Z6LIiBJY29uPSJTaG93TW9kZWxDaGFydHMiIC8+DQogICAgICAgICAgICA8Q21kIElEPSIzMjAzIiBCb3VuZHM9IjAsMSIgTmFtZT0iU2hvd01vZGVsU2tldGNoIiBBbGlhcz0i55CG6K66IiBJY29uPSJTaG93TW9kZWxTa2V0Y2giIC8+DQogICAgICAgICAgICA8Q21kIElEPSIzMjA0IiBCb3VuZHM9IjEsMSIgTmFtZT0iU2F2ZUFzTW9kZWxTa2V0Y2giIEFsaWFzPSLlrZjkuLrnpLrmhI8iIEljb249IlNhdmVBc01vZGVsU2tldGNoIiAvPiAgICAgICAgICAgIA0KICAgICAgIDwvR3JvdXA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9IlRvb2xTIiBBbGlhcz0i5omp5bGV5Yqf6IO9IiAgVmlzaWJsZT0iMCI+DQogICAgICAgICAgICA8Q21kIElEPSI5ODAxIiBCb3VuZHM9IjAsMCwyLDEiIE5hbWU9IkZsb3dUb1MiIEFsaWFzPSLmtYHph4/lj5jooajnmq4iIEljb249IkZsb3dUb1MiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI5MjAxIiBCb3VuZHM9IjAsMSwyLDEiIE5hbWU9Ik1peFZpc2Nvc2l0eSIgQWxpYXM9Iua3t+WQiOm7j+W6piIgSWNvbj0iTWl4VmlzY29zaXR5IiAvPg0KICAgICAgIDwvR3JvdXA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9IkpvYnMiIEFsaWFzPSLmiJDmnpznrqHnkIYiIFZpc2libGU9IjAiPg0KICAgICAgICAgICAgPENtZCBJRD0iMTAwOCIgQm91bmRzPSIwLDAiIE5hbWU9IlJzdExvYWQiIEFsaWFzPSLliqDovb3miJDmnpwiIEljb249IkxvYWRKb2JzIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMTAwOSIgQm91bmRzPSIxLDAiIE5hbWU9IlJzdFNhdmUiIFR5cGU9IjEiIEV4dE5hbWVzPSJSc3RTYXZlQ3VyO1JzdFNhdmVBbGwiIEV4dEluZm89IuS/neWtmOW9k+WJjeaIkOaenDvkv53lrZjmiYDmnInmiJDmnpwiIEFsaWFzPSLkv53lrZjmiJDmnpwiIEljb249IlNhdmVKb2JzIiAvPg0KICAgICAgICA8L0dyb3VwPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJXaW5kb3ciIEFsaWFzPSLnqpflj6PmmL7npLoiIFZpc2libGU9IjAiPg0KICAgICAgICAgICAgPENtZCBJRD0iOTAwMiIgQm91bmRzPSIwLDAiIE5hbWU9IlZpc2libGVNb2RlbHMiIEFsaWFzPSLmqKHlnovnqpflj6MiIEljb249IlZpc2libGVNb2RlbHMiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI5MDAzIiBCb3VuZHM9IjEsMCIgTmFtZT0iVmlzaWJsZVBhcmFtZXRlcnMiIEFsaWFzPSLlj4LmlbDnqpflj6MiIEljb249IlZpc2libGVQYXJhbWV0ZXJzIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTEwMSIgQm91bmRzPSIwLDEiIE5hbWU9IlZpc2libGVBbmFsQmFzaWMiIEFsaWFzPSLln7rnoYDkv6Hmga8iIEljb249IklucHV0QmFzaWMiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI5MTAyIiBCb3VuZHM9IjEsMSIgTmFtZT0iVmlzaWJsZUFuYWxQVlQiIEFsaWFzPSJQVlTmlbDmja4iIEljb249IklucHV0Rmx1aWQiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI5MTAzIiBCb3VuZHM9IjAsMiIgTmFtZT0iVmlzaWJsZUFuYWxEaWZmIiBBbGlhcz0iRElGRuaVsOaNriIgSWNvbj0iSW5wdXRGbHVpZCIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkxMDQiIEJvdW5kcz0iMSwyIiBOYW1lPSJWaXNpYmxlQW5hbFBzZXUiIEFsaWFzPSLmi5/ljovlipvmlbDmja4iIEljb249IklucHV0Rmx1aWQiIC8+DQogICAgICAgIDwvR3JvdXA+DQoNCiAgICA8L1RhYj4NCg0KICAgIDxUYWIgSUQ9IjciIE5hbWU9IlN5c1Rvb2wiIEFsaWFzPSLns7vnu5/phY3nva7lt6XlhbcoVCkiIFZpc2libGU9IjAiID4NCg0KICAgICAgICA8R3JvdXAgTmFtZT0iU3lzVG9vbCIgQWxpYXM9IumFjee9ruW3peWFtyI+DQogICAgICAgICAgICA8Q21kIElEPSI3MDAxIiBCb3VuZHM9IjAsMSwyLDEiIE5hbWU9IlN5c1Rvb2xzIiBBbGlhcz0i57O757uf6YWN572u5bel5YW3IiBJY29uPSJTeXNUb29scyIgIC8+DQogICAgICAgIDwvR3JvdXA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9Ik1vZGVsTWFuYWdlciIgQWxpYXM9IuaooeWei+euoeeQhiI+DQogICAgICAgICAgICA8Q21kIElEPSI3MDAyIiBCb3VuZHM9IjAsMCwyLDEiIE5hbWU9Ik1vZGVsU2NhbiIgQWxpYXM9IuaooeWei+afpeeciyIgSWNvbj0iTW9kZWxTY2FuIiAvPg0KICAgICAgICA8L0dyb3VwPg0KDQogICAgPC9UYWI+DQoNCiAgICA8VGFiIElEPSI4IiBOYW1lPSJSZXN1bHQiIEFsaWFzPSLmiJDmnpznrqHnkIYoUikiID4NCg0KICAgICAgICA8R3JvdXAgTmFtZT0iSm9icyIgQWxpYXM9IuaIkOaenOeuoeeQhiI+DQogICAgICAgICAgICA8Q21kIElEPSIxMDA4IiBCb3VuZHM9IjAsMCIgTmFtZT0iUnN0TG9hZCIgQWxpYXM9IuWKoOi9veaIkOaenCIgSWNvbj0iTG9hZEpvYnMiIC8+DQogICAgICAgICAgICA8Q21kIElEPSIxMDA5IiBCb3VuZHM9IjEsMCIgTmFtZT0iUnN0U2F2ZSIgVHlwZT0iMSIgRXh0TmFtZXM9IlJzdFNhdmVDdXI7UnN0U2F2ZUFsbCIgRXh0SW5mbz0i5L+d5a2Y5b2T5YmN5oiQ5p6cO+S/neWtmOaJgOacieaIkOaenCIgQWxpYXM9IuS/neWtmOaIkOaenCIgSWNvbj0iU2F2ZUpvYnMiIC8+DQogICAgICAgIDwvR3JvdXA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9IlJlc0NvbXBhcmUiIEFsaWFzPSLmiJDmnpzlr7nmr5QiPg0KICAgICAgICAgICAgPENtZCBJRD0iODAwMyIgQm91bmRzPSIwLDAsMiwxIiBOYW1lPSJSZXNDb21wYXJlIiBBbGlhcz0i5oiQ5p6c5a+55q+UIiBJY29uPSJSZXNDb21wYXJlIiAgLz4NCiAgICAgICAgPC9Hcm91cD4NCg0KICAgICAgICA8R3JvdXAgTmFtZT0iUHJpbnQiIEFsaWFzPSLmiqXlkYrmiZPljbAiPg0KICAgICAgICAgICAgPENtZCBJRD0iODAwMSIgQm91bmRzPSIwLDAiIE5hbWU9IlJlcG9ydENvbmZpZyIgQWxpYXM9IuaKpeWRiuiuvue9riIgSWNvbj0icmVwb3J0Q29uZmlnIiAgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjgwMDQiIEJvdW5kcz0iMSwwIiBOYW1lPSJQcmludFByZXZpZXciIEFsaWFzPSLmiqXlkYrpooTop4giIEljb249IlByZVByaW50IiAgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjgwMDIiIEJvdW5kcz0iMCwxIiBOYW1lPSJQcmludCIgQWxpYXM9IuaJk+WNsCjlkKtQREYpIiBJY29uPSJQcmludCIgIC8+DQogICAgICAgICAgICA8Q21kIElEPSI4MDA1IiBCb3VuZHM9IjEsMSIgTmFtZT0iRXhwb3J0V29yZCIgQWxpYXM9IuWvvOWHuihXb3JkKSIgSWNvbj0iV29yZDE2IiAgLz4NCiAgICAgICAgPC9Hcm91cD4NCg0KICAgICAgICA8R3JvdXAgTmFtZT0iV2luZG93IiBBbGlhcz0i56qX5Y+j5pi+56S6IiBWaXNpYmxlPSIwIj4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkwMDMiIEJvdW5kcz0iMCwwLDIsMSIgTmFtZT0iVmlzaWJsZVBhcmFtZXRlcnMiIEFsaWFzPSLlj4LmlbDnqpflj6MiIEljb249IlZpc2libGVQYXJhbWV0ZXJzIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTAwNCIgQm91bmRzPSIwLDEsMiwxIiBOYW1lPSJWaXNpYmxlUHR5cyIgQWxpYXM9IuWxnuaAp+eql+WPoyIgSWNvbj0iUHJvcGVydHlXaW5kb3ciIC8+DQoNCiAgICAgICAgPC9Hcm91cD4NCg0KICAgIDwvVGFiPg0KDQogICAgPFRhYiBJRD0iOSIgTmFtZT0iV2luZG93IiBBbGlhcz0i56qX5Y+jKFcpIiA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9IldpbmRvdyIgQWxpYXM9IuWfuuacrCI+DQogICAgICAgICAgICA8Q21kIElEPSI5MDAxIiBCb3VuZHM9IjAsMCwyLDEiIE5hbWU9IlZpc2libGVQcm9qVHJlZURhIiBBbGlhcz0i6aG555uu5qCRIiBJY29uPSJQcm9qVHJlZSIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkwMDgiIEJvdW5kcz0iMCwxLDIsMSIgTmFtZT0iVmlzaWJsZVByb2pUcmVlSmIiIEFsaWFzPSLliIbmnpDmoJEiIEljb249IlByb2pUcmVlIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTAwOSIgQm91bmRzPSIwLDIsMiwxIiBOYW1lPSJWaXNpYmxlUHJvalRyZWVScyIgQWxpYXM9IuaIkOaenOagkSIgSWNvbj0iUHJvalRyZWUiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI5MDAyIiBCb3VuZHM9IjAsMyIgTmFtZT0iVmlzaWJsZU1vZGVscyIgQWxpYXM9IuaooeWei+eql+WPoyIgSWNvbj0iVmlzaWJsZU1vZGVscyIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkwMDMiIEJvdW5kcz0iMSwzIiBOYW1lPSJWaXNpYmxlUGFyYW1ldGVycyIgQWxpYXM9IuWPguaVsOeql+WPoyIgSWNvbj0iVmlzaWJsZVBhcmFtZXRlcnMiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI5MDA0IiBCb3VuZHM9IjAsNCIgTmFtZT0iVmlzaWJsZVB0eXMiIEFsaWFzPSLlsZ7mgKfnqpflj6MiIEljb249IlByb3BlcnR5V2luZG93IiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTAwNSIgQm91bmRzPSIxLDQiIE5hbWU9IlZpc2libGVMb2dzIiBBbGlhcz0i5pel5b+X56qX5Y+jIiBJY29uPSJWaXNpYmxlTG9ncyIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkwMDYiIEJvdW5kcz0iMCw1IiBOYW1lPSJTdGFja2VkUHJvamVjdCIgQWxpYXM9Iumhueebrueql+S9kyIgSWNvbj0iU3RhY2tlZFByb2plY3QiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI5MDA3IiBCb3VuZHM9IjEsNSIgTmFtZT0iU3RhY2tlZE1kaSIgQWxpYXM9IuWIhuaekOeql+S9kyIgSWNvbj0iU3RhY2tlZE1kaSIgLz4NCiAgICAgICAgPC9Hcm91cD4NCg0KICAgICAgICA8R3JvdXAgTmFtZT0iV2luZG93TGF5b3V0IiBBbGlhcz0i56qX5Y+j5biD5bGAIj4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkwMTEiIEJvdW5kcz0iMCwwIiBOYW1lPSJXaW5kb3dMYXlvdXRIIiBJY29uT25seT0iMSIgVGlwcz0i5rC05bmz5biD5bGAIiBJY29uPSJXaW5kb3dMYXlvdXRIIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTAxMiIgQm91bmRzPSIxLDAiIE5hbWU9IldpbmRvd0xheW91dFYiIEljb25Pbmx5PSIxIiBUaXBzPSLnq5bnm7TluIPlsYAiIEljb249IldpbmRvd0xheW91dFYiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI5MDEzIiBCb3VuZHM9IjAsMSIgTmFtZT0iV2luZG93TGF5b3V0VCIgSWNvbk9ubHk9IjEiIFRpcHM9IuW5s+mTuuW4g+WxgCIgSWNvbj0iV2luZG93TGF5b3V0VCIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkwMTQiIEJvdW5kcz0iMSwxIiBOYW1lPSJXaW5kb3dMYXlvdXRDIiBJY29uT25seT0iMSIgVGlwcz0i5oqY5Y+g5biD5bGAIiBJY29uPSJXaW5kb3dMYXlvdXRDIiAvPg0KICAgICAgICA8L0dyb3VwPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJDbG9zZSIgQWxpYXM9IuWFs+mXrSI+ICAgICAgICANCiAgICAgICAgICAgIDxDbWQgSUQ9IjkwMjEiIEJvdW5kcz0iMCwwIiBOYW1lPSJDbG9zZUN1clduZCIgQWxpYXM9IuWFs+mXreW9k+WJjSIgSWNvbj0iQ2xvc2VBbGxXaW5kb3ciIC8+DQogICAgICAgICAgICA8Q21kIElEPSI5MDIyIiBCb3VuZHM9IjEsMCIgTmFtZT0iQ2xvc2VBbGxXbmRzIiBBbGlhcz0i5YWz6Zet5omA5pyJIiBJY29uPSJDbG9zZUFsbFdpbmRvdyIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkwMjMiIEJvdW5kcz0iMCwxIiBOYW1lPSJQcmV2V25kIiBBbGlhcz0i5LiK5LiA5LiqIiBJY29uT25seT0iMSIgSWNvbj0iVXAiIFRpcHM9IuS4iuS4gOS4queql+S9kyIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkwMjQiIEJvdW5kcz0iMSwxIiBOYW1lPSJOZXh0V25kIiBBbGlhcz0i5LiL5LiA5LiqIiBJY29uT25seT0iMSIgSWNvbj0iRG93biIgVGlwcz0i5LiL5LiA5Liq56qX5L2TIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTAyNSIgQm91bmRzPSIwLDIsMiwxIiBUeXBlPSI3IiBOYW1lPSJMaXN0V3hXbmRzIiBBbGlhcz0i56qX5L2TIiAvPg0KICAgICAgICA8L0dyb3VwPg0KDQogICAgPC9UYWI+DQoNCiAgICA8VGFiIElEPSIxMCIgTmFtZT0iSGVscCIgQWxpYXM9IuW4ruWKqShIKSIgPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJIZWxwIiBBbGlhcz0i5biu5YqpIj4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjEwMDAxIiBCb3VuZHM9IjAsMCwyLDEiIE5hbWU9IkxvZ1ZpZXciIEFsaWFzPSLml6Xlv5fmn6XnnIsoTCkiIEljb249IkxvZ1ZpZXciIC8+DQogICAgICAgICAgICA8Q21kIElEPSIxMDAwMiIgQm91bmRzPSIwLDEsMiwxIiBOYW1lPSJIZWxwIiBBbGlhcz0i5biu5YqpKEgpIiBJY29uPSJIZWxwIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMTAwMDgiIEJvdW5kcz0iMCwyLDIsMSIgTmFtZT0iVXBkYXRlTGlzdHMiIEFsaWFzPSLmm7TmlrDliJfooagoSSkiIEljb249IlVwZGF0ZUxpc3RzIiAvPg0KICAgICAgICA8L0dyb3VwPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJMYW5nIiBBbGlhcz0i6K+t6KiAIj4NCiAgICAgICAgICAgPENtZCBJRD0iMTAwMDkiIEJvdW5kcz0iMCwwLDIsMSIgTmFtZT0iTGFuZ1N3YXAiIEFsaWFzPSLliIfmjaLor63oqIAiIEljb249IkxhbmdTd2FwIiAvPg0KICAgICAgICA8L0dyb3VwPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJBYm91dCIgQWxpYXM9IuWFs+S6jiI+DQogICAgICAgICAgICA8Q21kIElEPSIxMDAwMyIgQm91bmRzPSIwLDAsMiwxIiBOYW1lPSJBYm91dCIgQWxpYXM9IuWFs+S6jihBKSIgSWNvbj0iV1RBSUFib3V0IiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMTAwMDQiIEJvdW5kcz0iMSwwIiBOYW1lPSJBYm91dFF0IiBBbGlhcz0i5YWz5LqOUXQoUSkiIEljb249IlF0IiBWaXNpYmxlPSIwIiAvPg0KICAgICAgICA8L0dyb3VwPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJMb2dpbiIgQWxpYXM9IueZu+W9lShEZWJ1ZykiPg0KICAgICAgICAgICAgPENtZCBJRD0iMTAwMDciIEJvdW5kcz0iMCwwIiBOYW1lPSJSZWdpc3RlciIgQWxpYXM9IihEZWJ1Zynova/ku7bms6jlhowoUikiIEljb249IlJlZ2lzdGVyIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMTAwMDUiIEJvdW5kcz0iMSwwIiBOYW1lPSJMb2dpbiIgQWxpYXM9IihEZWJ1ZynnlKjmiLfnmbvlvZUoVSkiIEljb249IkxvZ2luIiAvPg0KICAgICAgICA8L0dyb3VwPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJEZWJ1ZyIgQWxpYXM9Iuiwg+ivlShEZWJ1ZykiPg0KICAgICAgICAgICAgPENtZCBJRD0iMTAwMDYiIEJvdW5kcz0iMCwwLDIsMSIgTmFtZT0iKERlYnVnKSBTdW0gUGFyYW1ldGVycyIgQWxpYXM9IihEZWJ1ZynmsYfmgLvmqKHlnovlj4LmlbAiIEljb249IlN1bVBhcmEiIC8+DQogICAgICAgPC9Hcm91cD4NCiAgICA8L1RhYj4NCg0KPC9SaWJib24+DQo=
\ No newline at end of file
+77u/PD94bWwgcup_mpadmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4NCg0KPCEtLSDnvJbovpHkvbwzy/nlKggWE1MU3B5IHYyMDA2IFUgKGh0dHA6Ly93d3cuYWx0b3ZhLmNvbSkg55SxIGFueSAoYW55KSAtLT4NCjwhLS0qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqLS0+DQo8IS0tICAgIOacrOaWh+aho+eahOebrueahOaYr+W7uueri1dUQUnova/ku7bns7vnu5/nmoToj5zljZXlsYLmrKHlhbPns7so6ZKI5a+5UmliYm9u5qih5byPKSAgICAgICAgICAgICAgICAgICAgICAgLS0+DQo8IS0tICAgIEF1dGhvcihzKTogd2FuZ3pnICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC0tPg0KPCEtLSAgICBEYXRlOiAyMDI0MDcxOCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAtLT4NCjwhLS0qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqLS0+DQoNCjwhLS0qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqLS0+DQo8IS0tDQogICAgVGFiIOe6p+WIqw0KICAgICAgICBJRDogICAgICAgICAg5ZSv5LiA5qCH6K+GDQogICAgICAgIE5hbWXvvJogICAgICAg5ZCN56ew77yM6YCa5bi46Iux5paHDQogICAgICAgIEFsaWFz77yaICAgICAg5Yir5ZCN77yM6YCa5bi45Lit5paHDQogICAgICAgIEZpbGVNb2RlOiAgICDmmK/lkKbmlofku7ZNZW515qih5byP77yMMSBvciAwDQogICAgICAgIFZpc2libGXvvJogICAg5piv5ZCm5Y+v6KeB77yMMSBvciAwDQogICAgICAgIFRpcHPvvJogICAgICAg6L6F5Yqp6K+05piODQoNCiAgICAgICAgR3JvdXAg57qn5YirDQogICAgICAgICAgICBOYW1l77yaICAgICAgIOWQjeensO+8jOmAmuW4uOiLseaWhw0KICAgICAgICAgICAgQWxpYXPvvJogICAgICDliKvlkI3vvIzpgJrluLjkuK3mlocNCg0KICAgICAgICAgICAgQ21kIOe6p+WIqw0KICAgICAgICAgICAgICAgIElEOiAgICAgICAgICDllK/kuIDmoIfor4YNCiAgICAgICAgICAgICAgICBUeXBlOiAgICAgICAg5a+55bqU5o6n5Lu257G75Z6LOg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAw4oCU4oCU6buY6K6kQnV0dG9uDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIDHigJTigJTluKbkuIvmi4noj5zljZVCdXR0b24NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMuKAlOKAlENvbWJvQm94DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIDPigJTigJRDaGVja0JveA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICA04oCU4oCUUmFkaW9CdXR0b24NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgNeKAlOKAlFRleHQNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgNuKAlOKAlExhYmVsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIDfigJTigJRMaXN0V2lkZ2V0DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIDjigJTigJRMaW5lRWRpdA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICA54oCU4oCU5YqI5YiG5oyJ6ZKuDQogICAgICAgICAgICAgICAgTmFtZe+8miAgICAgICDlkI3np7DvvIzpgJrluLjoi7HmlocNCiAgICAgICAgICAgICAgICBBbGlhc++8miAgICAgIOWIq+WQje+8jOmAmuW4uOS4reaWhw0KICAgICAgICAgICAgICAgIEljb27vvJogICAgICAg5Zu+5qCHDQogICAgICAgICAgICAgICAgU2hvcnRLZXnvvJogICDlv6vmjbfplK4NCiAgICAgICAgICAgICAgICBCb3VuZHM6ICAgICAg5L2N572u5L+h5oGv77yM5YWo5piv5pW05pWw77yM5ZyoR3JpZExheW91dOS4rQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoMCwwLDEsMikgKDAsMCkg5YiG5Yir5Li6eHl3aA0KICAgICAgICAgICAgICAgIEV4dEluZm86ICAgICDmianlsZXkv6Hmga/vvIzlpoLmk43kvZzlr7nosaHnmoTooajlkI0s5LiL5ouJ6YCJ6aG5562JDQogICAgICAgICAgICAgICAgRXh0TmFtZXM6ICAgIOaJqeWxleS/oeaBr+WvueW6lOeahE5hbWXvvIzlpoLkuIvmi4lidXR0b27lr7nlupTnmoROYW1lDQogICAgICAgICAgICAgICAgVGlwc++8miAgICAgICDovoXliqnor7TmmI4NCi0tPg0KPCEtLSoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiotLT4NCg0KPFJpYmJvbj4NCg0KICAgIDxUYWIgSUQ9IjEiIE5hbWU9IlByb2pNYW5hZ2VyIiBBbGlhcz0i6aG555uu566h55CGKFApIiBGaWxlTW9kZT0iMSIgPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJQcm9qZWN0IiBBbGlhcz0i5paH5Lu2Ij4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjEwMDAiIE5hbWU9IkFwcEhvbWUiIEFsaWFzPSIiIEljb249IkFwcEhvbWUxMjgiIC8+DQogICAgICAgICAgICA8Q21kIElEPSItMSIgTmFtZT0iU2VwYXJhdG9yIiBBbGlhcz0i5YiG6ZqU56ymIiBUaXBzPSIiIC8+DQogICAgICAgICAgICA8Q21kIElEPSIxMDAxIiBOYW1lPSJQcm9qTmV3IiBBbGlhcz0i5paw5bu66aG555uuIiBTaG9ydEtleT0iQ3RybCtOIiBJY29uPSJOZXdQcm9qIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMTAwMiIgTmFtZT0iUHJvak9wZW4iIEFsaWFzPSLmiZPlvIDpobnnm64iIFNob3J0S2V5PSJDdHJsK08iIEljb249Ik9wZW5Qcm9qIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMTAwMyIgTmFtZT0iUHJvakNsb3NlIiBBbGlhcz0i5YWz6Zet6aG555uuIiBJY29uPSJDbG9zZVByb2oiIC8+DQogICAgICAgICAgICA8Q21kIElEPSItMSIgTmFtZT0iU2VwYXJhdG9yIiBBbGlhcz0i5YiG6ZqU56ymIiBUaXBzPSIiIC8+DQogICAgICAgICAgICA8Q21kIElEPSIxMDA1IiBOYW1lPSJQcm9qU2F2ZSIgQWxpYXM9IuS/neWtmOmhueebriIgU2hvcnRLZXk9IkN0cmwrUyIgSWNvbj0iU2F2ZVByb2oiIC8+DQogICAgICAgICAgICA8Q21kIElEPSIxMDA2IiBOYW1lPSJQcm9qU2F2ZUFzIiBBbGlhcz0i6aG555uu5Y+m5a2YIiBJY29uPSJTYXZlYXMiIC8+DQogICAgICAgICAgICA8Q21kIElEPSIxMDA3IiBOYW1lPSJQcm9qQ29uZmlnIiBBbGlhcz0i6aG555uu5L+h5oGvIiBJY29uPSJQcm9qSW5mbyIgLz4NCg0KICAgICAgICAgICAgPENtZCBJRD0iLTEiIE5hbWU9IlNlcGFyYXRvciIgQWxpYXM9IuWIhumalOespiIgVGlwcz0iIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMTAwMDIiIE5hbWU9IkhlbHAiIEFsaWFzPSLluK7liqkoSCkiIEljb249IkhlbHAiIC8+DQogICAgICAgICAgICA8Q21kIElEPSIxMDAwMyIgTmFtZT0iQWJvdXQiIEFsaWFzPSLlhbPkuo4oQSkiIEljb249IldUQUlBYm91dCIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjEwMDA4IiBOYW1lPSJVcGRhdGVMaXN0cyIgQWxpYXM9IuabtOaWsOWIl+ihqChJKSIgSWNvbj0iVXBkYXRlTGlzdHMiIC8+DQogICAgICAgICAgICA8Q21kIElEPSItMSIgTmFtZT0iU2VwYXJhdG9yIiBBbGlhcz0i5YiG6ZqU56ymIiBUaXBzPSIiIC8+DQogICAgICAgICAgICA8Q21kIElEPSIxMDEwIiBOYW1lPSJBcHBRdWl0IiBBbGlhcz0i6YCA5Ye6KFgpIiBJY29uPSJDbG9zZSIgLz4NCiAgICAgICAgPC9Hcm91cD4NCiAgICA8L1RhYj4NCg0KICAgIDxUYWIgSUQ9IjAiIE5hbWU9IldlbENvbWUiIEFsaWFzPSLlvIDlp4soTykiID4NCg0KICAgICAgICA8R3JvdXAgTmFtZT0iRGF0YU1hbmFnZXIiIEFsaWFzPSLmlbDmja7lh4blpIciPg0KICAgICAgICAgICAgPENtZCBJRD0iMTA5OSIgQm91bmRzPSIwLDAsMiwxIiBOYW1lPSJXZWxsTmV3IiBBbGlhcz0i5paw5bu65LqVKFcpIiBJY29uPSJXZWxsTmV3IiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMjAwNSIgQm91bmRzPSIwLDEsMiwxIiBOYW1lPSJEYXRhUmF0ZSIgQWxpYXM9Iua1gemHj+aVsOaNrihRKSIgRXh0SW5mbz0iUF9EQVRBX0dBVUdFX0YiIEljb249IlJhdGVEYXRhIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMjAwNiIgQm91bmRzPSIwLDIsMiwxIiBOYW1lPSJEYXRhUHJlIiBBbGlhcz0i5Y6L5Yqb5pWw5o2uKFApIiBFeHRJbmZvPSJQX0RBVEFfR0FVR0VfUCIgSWNvbj0iUHJlc3N1cmVEYXRhIiAvPg0KICAgICAgICA8L0dyb3VwPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJBbmFsRWRpdCIgQWxpYXM9IuWIhuaekOeuoeeQhiI+DQogICAgICAgICAgICA8Q21kIElEPSIzMDA2IiBCb3VuZHM9IjAsMCwyLDEiIE5hbWU9IkFuYWxOZXciIEFsaWFzPSLmlrDlu7rliIbmnpAiIEljb249IkpvYk5ldyIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjMwMDciIEJvdW5kcz0iMCwxLDIsMSIgTmFtZT0iQW5hbEVkaXQiIEFsaWFzPSLliIbmnpDnrqHnkIYiIEljb249IkpvYkVkaXQiIFZpc2libGU9IjAiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI5MTAxIiBCb3VuZHM9IjAsMSIgTmFtZT0iVmlzaWJsZUFuYWxCYXNpYyIgQWxpYXM9IuWfuuehgOS/oeaBryIgSWNvbj0iSW5wdXRCYXNpYyIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkxMDIiIEJvdW5kcz0iMSwxIiBOYW1lPSJWaXNpYmxlQW5hbFBWVCIgQWxpYXM9IlBWVOaVsOaNriIgSWNvbj0iSW5wdXRGbHVpZCIgLz4NCiAgICAgICAgPC9Hcm91cD4NCg0KICAgICAgICA8R3JvdXAgTmFtZT0iQW5hbHl0aWNhbCIgQWxpYXM9Iua1geWKqOauteWIhuaekCI+DQogICAgICAgICAgICA8Q21kIElEPSIzMDAzIiBCb3VuZHM9IjAsMCwyLDEiIE5hbWU9IkFuYWxQRiIgQWxpYXM9Iua1geWKqOautemAieaLqSIgRXh0SW5mbz0iUEYiIEljb249IlBGIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMzAwNCIgQm91bmRzPSIwLDEsMiwxIiBOYW1lPSJBbmFsRmxvd1NlZyIgQWxpYXM9Iua1geWKqOauteWIhuaekCIgSWNvbj0iRmxvd1BlcmlvZCIgLz4NCiAgICAgICAgPC9Hcm91cD4NCg0KICAgICAgICA8R3JvdXAgTmFtZT0iQW5hbHl0aWNhbCIgQWxpYXM9Iuino+mHiuaLn+WQiCI+DQoNCiAgICAgICAgICAgIDxDbWQgSUQ9IjMxMDUiIEJvdW5kcz0iMCwwLDIsMSIgTmFtZT0iRGVjb252b2x2IiBBbGlhcz0i5Y+N6KS256evIiBJY29uPSJEZWNvbnZvbHYiIFZpc2libGU9IjAiIC8+DQogICAgICAgICAgICA8Q21kIElEPSIzMTAxIiBCb3VuZHM9IjAsMSwyLDEiIE5hbWU9IkZpdE1vZGVsIiBBbGlhcz0i6Kej5p6Q6KejIiBJY29uPSJGaXRNb2RlbCIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjMxMDQiIEJvdW5kcz0iMCwyLDIsMSIgTmFtZT0ibm1GaXRNb2RlbCIgQWxpYXM9IuaVsOWAvOinoyIgSWNvbj0iRml0TW9kZWwiIC8+DQoNCiAgICAgICAgICAgIDxDbWQgSUQ9IjMxMDIiIEJvdW5kcz0iMCwzLDIsMSIgTmFtZT0iQXV0b0ZpdCIgQWxpYXM9IuiHquWKqOaLn+WQiCIgSWNvbj0iQXV0b0ZpdCIgLz4NCiAgICAgICA8L0dyb3VwPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJOdW1lcmljYWwiIEFsaWFzPSLlnLDotKjlu7rmqKEoRGVidWcpIiBWaXNpYmxlPSIwIj4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjUwMDIiIEJvdW5kcz0iMCwwLDIsMSIgTmFtZT0iUHJvcGVydHlMb2FkIiBBbGlhcz0i5bGe5oCn5a+85YWlIiBJY29uPSJQcmVwYXJlR3JpZCIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjUxMDIiIEJvdW5kcz0iMCwxLDIsMSIgTmFtZT0iUnVuR3JpZCIgQWxpYXM9Iue9keagvOWIkuWIhiIgSWNvbj0iUGxhdGVGaXQiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI1MjAxIiBCb3VuZHM9IjAsMiwyLDEiIE5hbWU9IkFuYWxNYXAiIEFsaWFzPSLorqHnrpciIEljb249IlJ1bkV4IiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iNTIwMiIgQm91bmRzPSIwLDMsMiwxIiBOYW1lPSJBbmFsUEYiIEFsaWFzPSLovoXliqnmi5/lkIgiIEV4dEluZm89IlBGIiBJY29uPSJSdW5PdGhlciIgVmlzaWJsZT0iMCIvPg0KICAgICAgIDwvR3JvdXA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9IldlbGxNYXAiIEFsaWFzPSLkupXkvY3lm74iPg0KICAgICAgICAgICAgPENtZCBJRD0iMzAwOCIgQm91bmRzPSIwLDAsMiwxIiBOYW1lPSJBbmFsTWFwIiBBbGlhcz0i5LqV5L2N5Zu+IiBJY29uPSJNYXAyRCIgVmlzaWJsZT0iMSIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjMwMTgiIEJvdW5kcz0iMCwxLDIsMSIgTmFtZT0iQW5hbEludGVyZmVyZSIgQWxpYXM9IuW5suaJsOiuvuWumiIgSWNvbj0iTWFwMkQiIFZpc2libGU9IjAiIC8+DQogICAgICAgIDwvR3JvdXA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9IldpbmRvdyIgQWxpYXM9Iueql+WPo+aYvuekuihEZWJ1ZykiIFZpc2libGU9IjAiID4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkwMDIiIEJvdW5kcz0iMCwwIiBOYW1lPSJWaXNpYmxlTW9kZWxzIiBBbGlhcz0i5qih5Z6L56qX5Y+jIiBJY29uPSJWaXNpYmxlTW9kZWxzIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTAwMyIgQm91bmRzPSIxLDAiIE5hbWU9IlZpc2libGVQYXJhbWV0ZXJzIiBBbGlhcz0i5Y+C5pWw56qX5Y+jIiBJY29uPSJWaXNpYmxlUGFyYW1ldGVycyIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkxMDEiIEJvdW5kcz0iMCwxIiBOYW1lPSJWaXNpYmxlQW5hbEJhc2ljIiBBbGlhcz0i5Z+656GA5L+h5oGvIiBJY29uPSJJbnB1dEJhc2ljIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTEwMiIgQm91bmRzPSIxLDEiIE5hbWU9IlZpc2libGVBbmFsUFZUIiBBbGlhcz0iUFZU5pWw5o2uIiBJY29uPSJJbnB1dEZsdWlkIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTEwMyIgQm91bmRzPSIwLDIiIE5hbWU9IlZpc2libGVBbmFsRGlmZiIgQWxpYXM9IkRJRkbmlbDmja4iIEljb249IklucHV0Rmx1aWQiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI5MTA0IiBCb3VuZHM9IjEsMiIgTmFtZT0iVmlzaWJsZUFuYWxQc2V1IiBBbGlhcz0i5ouf5Y6L5Yqb5pWw5o2uIiBJY29uPSJJbnB1dEZsdWlkIiAvPg0KICAgICAgICA8L0dyb3VwPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJIZWxwIiBBbGlhcz0i5biu5YqpIj4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjEwMDAyIiBCb3VuZHM9IjAsMCwyLDEiIE5hbWU9IkhlbHAiIEFsaWFzPSLluK7liqkoSCkiIEljb249IkhlbHAiIC8+DQogICAgICAgIDwvR3JvdXA+DQoNCiAgICA8L1RhYj4NCg0KDQogICAgPFRhYiBJRD0iMiIgTmFtZT0iRGF0YU1hbmFnZXIiIEFsaWFzPSLmlbDmja7nrqHnkIYoRCkiID4NCg0KICAgICAgICA8R3JvdXAgTmFtZT0iRGF0YU1hbmFnZXIiIEFsaWFzPSLkupUiPg0KICAgICAgICAgICAgPENtZCBJRD0iMTA5OSIgQm91bmRzPSIwLDAsMiwxIiBOYW1lPSJXZWxsTmV3IiBBbGlhcz0i5paw5bu65LqVKFcpIiBJY29uPSJXZWxsTmV3IiAvPg0KICAgICAgICA8L0dyb3VwPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJEYXRhTWFuYWdlciIgQWxpYXM9IuWfuuehgOaVsOaNriI+DQogICAgICAgICAgICA8Q21kIElEPSIyMDAxIiBCb3VuZHM9IjAsMCwyLDEiIE5hbWU9IkRhdGFXZWxsQmFzaWMiIEFsaWFzPSLkupXln7rnoYDmlbDmja4oQikiIEV4dEluZm89IkJfV0VMTCIgSWNvbj0iQmFzaWNEYXRhIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMjAwMiIgQm91bmRzPSIwLDEsMiwxIiBOYW1lPSJEYXRhTGF5ZXIiIEFsaWFzPSLlnLDotKjliIblsYLmlbDmja4oTCkiIEV4dEluZm89IkJfTEFZRVIiIEljb249IkxheWVyRGF0YSIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjIwMDMiIEJvdW5kcz0iMCwyLDIsMSIgTmFtZT0iRGF0YVJlcyIgQWxpYXM9IuWCqOWxguaVsOaNrihSKSIgRXh0SW5mbz0iUF9EQVRBX1JFUyIgSWNvbj0iUmVzRGF0YSIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjIwMDQiIEJvdW5kcz0iMCwzLDIsMSIgTmFtZT0iRGF0YUZsdSIgQWxpYXM9Iua1geS9k+aAp+i0qOaVsOaNrihGKSIgRXh0SW5mbz0iUF9EQVRBX0ZMVUlEIiBJY29uPSJGbHVpZFByb3BlcnR5IiAvPg0KICAgICAgICA8L0dyb3VwPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJEYXRhTWFuYWdlciIgQWxpYXM9IuWOi+WKm+a1gemHjyI+DQogICAgICAgICAgICA8Q21kIElEPSIyMDA1IiBCb3VuZHM9IjAsMCwyLDEiIE5hbWU9IkRhdGFSYXRlIiBBbGlhcz0i5rWB6YeP5pWw5o2uKFEpIiBFeHRJbmZvPSJQX0RBVEFfR0FVR0VfRiIgSWNvbj0iUmF0ZURhdGEiIC8+DQogICAgICAgICAgICA8Q21kIElEPSIyMDA2IiBCb3VuZHM9IjAsMSwyLDEiIE5hbWU9IkRhdGFQcmUiIEFsaWFzPSLljovlipvmlbDmja4oUCkiIEV4dEluZm89IlBfREFUQV9HQVVHRV9QIiBJY29uPSJQcmVzc3VyZURhdGEiIC8+DQogICAgICAgIDwvR3JvdXA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9IkdYNiIgQWxpYXM9IuW5s+WPsOS6kumAmiI+DQogICAgICAgICAgICA8Q21kIElEPSIyMDA3IiBCb3VuZHM9IjAsMCwyLDEiIE5hbWU9Ikd4NkNvbm5lY3RTZXJ2ZXIiIEFsaWFzPSJHWDbkupLpgJooQykiIEljb249Ikd4NkNvbm5lY3RTZXJ2ZXIiIC8+DQogICAgICAgICAgICA8Q21kIElEPSIyMDA4IiBCb3VuZHM9IjAsMSwyLDEiIE5hbWU9Ikd4NkdldFRhc2tzIiBBbGlhcz0i6I635Y+W5Lu75YqhKEQpIiBJY29uPSJHeDZHZXRUYXNrcyIgIFZpc2libGU9IjAiLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjIwMDkiIEJvdW5kcz0iMCwyLDIsMSIgTmFtZT0iR3g2VXBkYXRlVGFza3MiIEFsaWFzPSLmm7TmlrDnirbmgIEoVSkiIEljb249Ikd4NlVwZGF0ZVRhc2tzIiAgVmlzaWJsZT0iMCIvPg0KICAgICAgICA8L0dyb3VwPg0KDQogICAgPC9UYWI+DQoNCiAgICA8VGFiIElEPSIyMDEiIE5hbWU9IkRhdGFFZGl0IiBBbGlhcz0i5pWw5o2u57yW6L6RKEUpIiA+DQogICAgICAgIDxHcm91cCBOYW1lPSJEYXRhRWRpdCIgQWxpYXM9IuaVsOaNrue8lui+kSI+DQogICAgICAgICAgICA8Q21kIElEPSIzMDAxIiBCb3VuZHM9IjAsMCwyLDEiIE5hbWU9IkFuYWxGbHUiIEFsaWFzPSLmtYHph4/nvJbovpEiIEV4dEluZm89IkYiIE1kaVR5cGU9IkRhdGFFZGl0IiBJY29uPSJSYXRlRGF0YSIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjMwMDIiIEJvdW5kcz0iMCwxLDIsMSIgTmFtZT0iQW5hbFByZXNzIiBBbGlhcz0i5Y6L5Yqb57yW6L6RIiBFeHRJbmZvPSJQIiBNZGlUeXBlPSJEYXRhRWRpdCIgSWNvbj0iUHJlc3N1cmVEYXRhIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMzMwMyIgQm91bmRzPSIwLDIsMiwxIiBOYW1lPSJBbmFsUHJlQ29uIiBBbGlhcz0i5Y6L5Yqb5oqY566XIiBFeHRJbmZvPSJQIiBNZGlUeXBlPSJEYXRhRWRpdCIgSWNvbj0iQW5hbFByZUNvbiIgLz4NCiAgICAgICAgPC9Hcm91cD4NCiAgICA8L1RhYj4NCg0KICAgIDxUYWIgSUQ9IjMiIE5hbWU9IkFuYWx5dGljYWxUZXN0IiBBbGlhcz0i5aSE55CG6Kej6YeKKEEpIiA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9IkFuYWxFZGl0IiBBbGlhcz0i5YiG5p6Q566h55CGIj4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjMwMDYiIEJvdW5kcz0iMCwwIiBOYW1lPSJBbmFsTmV3IiBBbGlhcz0i5paw5bu65YiG5p6QIiBJY29uPSJKb2JOZXciIC8+DQogICAgICAgICAgICA8Q21kIElEPSIzMDA3IiBCb3VuZHM9IjEsMCIgTmFtZT0iQW5hbEVkaXQiIEFsaWFzPSLliIbmnpDnrqHnkIYiIEljb249IkpvYkVkaXQiIC8+DQogICAgICAgIDwvR3JvdXA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9IlNlZ0FuYWwiIEFsaWFzPSLmtYHliqjmrrXliIbmnpAiPg0KICAgICAgICAgICAgPENtZCBJRD0iMzAwMyIgQm91bmRzPSIwLDAsMiwxIiBOYW1lPSJBbmFsUEYiIEFsaWFzPSLmtYHliqjmrrXpgInmi6kiIEV4dEluZm89IlBGIiBJY29uPSJQRiIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjMwMDQiIEJvdW5kcz0iMCwxLDIsMSIgTmFtZT0iQW5hbEZsb3dTZWciIEFsaWFzPSLmtYHliqjmrrXliIbmnpAiIEljb249IkZsb3dQZXJpb2QiIC8+DQogICAgICAgICAgICA8Q21kIElEPSIzMDA1IiBCb3VuZHM9IjAsMiwyLDEiIE5hbWU9IkFuYWxPdGhlcnMiIEFsaWFzPSLnibnlvoHnur/liIbmnpAiIFR5cGU9IjEiICBWaXNpYmxlPSIwIiBFeHROYW1lcz0iQ2hhcnRUO0NoYXJ0U3FydFQ7Q2hhcnQyNVQ7Q2hhcnQ1VCIgRXh0SW5mbz0iQ2hhcnQgVDtDaGFydCBTcXJ0KFQpO0NoYXJ0IDAuMjVUO0NoYXJ0IC0wLjVUIiBJY29uPSJBc3Npc0FuYWwiIC8+DQogICAgICAgICAgICA8Q21kIElEPSIzMDEwIiBCb3VuZHM9IjAsMywyLDEiIE5hbWU9IkFuYWxXbmRNIiBBbGlhcz0i5rWB5Yqo5q6156qX5Y+jIiBUeXBlPSIxIiBJY29uPSJBbmFsV25kTSIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjMwMDkiIEJvdW5kcz0iMCw0LDIsMSIgTmFtZT0iQW5hbERpc3RyaSIgQWxpYXM9IuWIhuW4g+WbviIgVHlwZT0iMSIgRXh0TmFtZXM9IkNoYXJ0RGVuO0NoYXJ0VmlzIiBFeHRJbmZvPSLmtZPluqbliIbluIPlm7476buP5bqm5YiG5biD5Zu+IiBJY29uPSJBbmFsRGlzdHJpIiAvPg0KICAgICAgICA8L0dyb3VwPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJEYXRhRml0IiBBbGlhcz0i6Kej6YeK5ouf5ZCIIj4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjMxMDUiIEJvdW5kcz0iMCwwLDIsMSIgTmFtZT0iRGVjb252b2x2IiBBbGlhcz0i5Y+N6KS256evKERlYnVnKSIgSWNvbj0iRGVjb252b2x2IiAvPg0KDQogICAgICAgICAgICA8Q21kIElEPSIzMTAxIiBCb3VuZHM9IjAsMSwyLDEiIE5hbWU9IkZpdE1vZGVsIiBBbGlhcz0i6Kej5p6Q6KejIiBJY29uPSJGaXRNb2RlbCIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjMxMDQiIEJvdW5kcz0iMCwyLDIsMSIgTmFtZT0ibm1GaXRNb2RlbCIgQWxpYXM9IuaVsOWAvOinoyIgSWNvbj0iRml0TW9kZWwiIC8+DQogICAgICAgICAgICA8Q21kIElEPSIzMTAyIiBCb3VuZHM9IjAsMywyLDEiIE5hbWU9IkF1dG9GaXQiIEFsaWFzPSLoh6rliqjmi5/lkIgiIEljb249IkF1dG9GaXQiIC8+DQogICAgICAgICAgICA8Q21kIElEPSIzMTAzIiBCb3VuZHM9IjAsNCwyLDEiIE5hbWU9IlBsYXRlRml0IiBBbGlhcz0i5pWP5oSf5oCn5YiG5p6QIiBJY29uPSJQbGF0ZUZpdCIgLz4NCiAgICAgICA8L0dyb3VwPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJBSVRlc3QiIEFsaWFzPSLmmbrog73or5XkupUiPg0KICAgICAgICAgICAgPENtZCBJRD0iMzkwMSIgQm91bmRzPSIwLDAsMiwxIiBOYW1lPSJNb2RlbENsYXNzaWZ5IiBBbGlhcz0i5qih5Z6L6K+G5YirIiBJY29uPSJNb2RlbENsYXNzaWZ5IiAvPg0KICAgICAgICA8L0dyb3VwPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJSZWxhdGl2ZVRvb2wiIEFsaWFzPSLnm7jlhbPlt6XlhbciPg0KICAgICAgICAgICAgPENtZCBJRD0iMzIwMSIgQm91bmRzPSIwLDAsMiwxIiBOYW1lPSJUaW1lIiBBbGlhcz0i5pe26Ze0IiBJY29uPSJUaW1lIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMzIwMiIgQm91bmRzPSIwLDEiIE5hbWU9IlNob3dNb2RlbENoYXJ0cyIgQWxpYXM9IuaooeWei+ekuuaEjyIgSWNvbj0iU2hvd01vZGVsQ2hhcnRzIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMzIwNCIgQm91bmRzPSIxLDEiIE5hbWU9IlNhdmVBc01vZGVsU2tldGNoIiBBbGlhcz0i5a2Y5Li656S65oSPIiBJY29uPSJTYXZlQXNNb2RlbFNrZXRjaCIgLz4NCg0KICAgICAgIDwvR3JvdXA+DQoNCjwhLS0gICAgICAgICAgICAgICAgICAgIDxDbWQgSUQ9IjMyMDMiIEJvdW5kcz0iMCwxIiBOYW1lPSJTaG93TW9kZWxTa2V0Y2giIEFsaWFzPSLnkIborroiIEljb249IlNob3dNb2RlbFNrZXRjaCIgLz48R3JvdXAgTmFtZT0iVG9vbFMiIEFsaWFzPSLmianlsZXlip/og70iPg0KICAgICAgICAgICAgPENtZCBJRD0iOTgwMSIgQm91bmRzPSIwLDAsMiwxIiBOYW1lPSJGbG93VG9TIiBBbGlhcz0i5rWB6YeP5Y+Y6KGo55quIiBJY29uPSJGbG93VG9TIiBWaXNpYmxlPSIwIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTIwMSIgQm91bmRzPSIwLDEsMiwxIiBOYW1lPSJNaXhWaXNjb3NpdHkiIEFsaWFzPSLmt7flkIjpu4/luqYiIEljb249Ik1peFZpc2Nvc2l0eSIgVmlzaWJsZT0iMCIgLz4NCiAgICAgICA8L0dyb3VwPi0tPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJKb2JzIiBBbGlhcz0i5oiQ5p6c566h55CGIj4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjEwMDgiIEJvdW5kcz0iMCwwIiBOYW1lPSJSc3RMb2FkIiBBbGlhcz0i5Yqg6L295oiQ5p6cIiBJY29uPSJMb2FkSm9icyIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjEwMDkiIEJvdW5kcz0iMSwwIiBOYW1lPSJSc3RTYXZlIiBUeXBlPSIxIiBFeHROYW1lcz0iUnN0U2F2ZUN1cjtSc3RTYXZlQWxsIiBFeHRJbmZvPSLkv53lrZjlvZPliY3miJDmnpw75L+d5a2Y5omA5pyJ5oiQ5p6cIiBBbGlhcz0i5L+d5a2Y5oiQ5p6cIiBJY29uPSJTYXZlSm9icyIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjEwMTEiIEJvdW5kcz0iMCwxLDIsMSIgTmFtZT0iVG9OdW1lcmljYWwiIEFsaWFzPSJUby3mlbDlgLwiIEljb249IkxvYWRKb2JzIiBWaXNpYmxlPSIwIiAvPg0KICAgICAgICA8L0dyb3VwPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJXaW5kb3ciIEFsaWFzPSLnqpflj6PmmL7npLoiPg0KICAgICAgICAgICAgPENtZCBJRD0iOTAwMiIgQm91bmRzPSIwLDAiIE5hbWU9IlZpc2libGVNb2RlbHMiIEFsaWFzPSLmqKHlnovnqpflj6MiIEljb249IlZpc2libGVNb2RlbHMiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI5MDAzIiBCb3VuZHM9IjEsMCIgTmFtZT0iVmlzaWJsZVBhcmFtZXRlcnMiIEFsaWFzPSLlj4LmlbDnqpflj6MiIEljb249IlZpc2libGVQYXJhbWV0ZXJzIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTEwMSIgQm91bmRzPSIwLDEiIE5hbWU9IlZpc2libGVBbmFsQmFzaWMiIEFsaWFzPSLln7rnoYDkv6Hmga8iIEljb249IklucHV0QmFzaWMiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI5MTAyIiBCb3VuZHM9IjEsMSIgTmFtZT0iVmlzaWJsZUFuYWxQVlQiIEFsaWFzPSJQVlTmlbDmja4iIEljb249IklucHV0Rmx1aWQiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI5MTAzIiBCb3VuZHM9IjAsMiIgTmFtZT0iVmlzaWJsZUFuYWxEaWZmIiBBbGlhcz0iRElGRuaVsOaNriIgSWNvbj0iSW5wdXRGbHVpZCIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkxMDQiIEJvdW5kcz0iMSwyIiBOYW1lPSJWaXNpYmxlQW5hbFBzZXUiIEFsaWFzPSLmi5/ljovlipvmlbDmja4iIEljb249IklucHV0Rmx1aWQiIC8+DQogICAgICAgIDwvR3JvdXA+DQogICAgPC9UYWI+DQoNCiAgICA8VGFiIElEPSI1IiBOYW1lPSJOdW1lcmljYWxUZXN0IiBBbGlhcz0i5pWw5YC85bu65qihKE4pIiA+DQogICAgICAgIDxHcm91cCBOYW1lPSJObU1hbmFnZXIiIEFsaWFzPSLliIbmnpDnrqHnkIYiIFZpc2libGU9IjAiPg0KICAgICAgICAgICAgPENtZCBJRD0iNTAwMSIgQm91bmRzPSIwLDAsMiwxIiBOYW1lPSJBbmFsTmV3IiBBbGlhcz0i5Li05pe25rWL6K+VMSIgSWNvbj0iUHJlcGFyZUdyaWQiIFZpc2libGU9IjAiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI1MDAyIiBCb3VuZHM9IjAsMSwyLDEiIE5hbWU9IlByb3BlcnR5TG9hZCIgQWxpYXM9IuS4tOaXtua1i+ivlTIiIEljb249IlByZXBhcmVHcmlkIiAgVmlzaWJsZT0iMCIvPg0KICAgICAgICA8L0dyb3VwPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJObUFuYWxDaGFuZ2UiIEFsaWFzPSLliIbmnpDliIfmjaIiPg0KICAgICAgICAgICAgPENtZCBJRD0iNTEzMCIgQm91bmRzPSIwLDAiIE5hbWU9Ik5tQW5hbENoYW5nZSIgQWxpYXM9IuWIhuaekOWIh+aNoiIgSWNvbj0iSm9iRWRpdCIgLz4NCiAgICAgICA8L0dyb3VwPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJOdEluaXQiIEFsaWFzPSLmqKHlnovlh6DkvZXlr7nosaEiPg0KICAgICAgICAgICAgPENtZCBJRD0iNTExOCIgQm91bmRzPSIwLDAsMiwxIiBOYW1lPSJObU1hcCIgQWxpYXM9Ik1hcCIgSWNvbj0iTm1JbWFnZSIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjUxMTkiIEJvdW5kcz0iMCwxLDIsMSIgTmFtZT0iTm1VbmxvY2tlZCIgQWxpYXM9IumUgeWumiIgSWNvbj0iTm1VbmxvY2tlZCIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjUxMDIiIEJvdW5kcz0iMCwyLDIsMSIgTmFtZT0iTm1JbWFnZSIgQWxpYXM9IuayueiXj+WcsOWbviIgSWNvbj0iTm1JbWFnZSIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjUxMjAiIEJvdW5kcz0iMCwzLDIsMSIgTmFtZT0iTm1NZWFzdXJlIiBBbGlhcz0i5q+U5L6L5bC6IiBJY29uPSJObU1lYXN1cmUiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI1MTAzIiBCb3VuZHM9IjAsNCwyLDEiIE5hbWU9Ik5tUG9seWdvbiIgQWxpYXM9IuWkmui+ueW9oui+ueeVjCIgSWNvbj0iTm1Qb2x5Z29uIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iNTEwNCIgQm91bmRzPSIwLDUiIE5hbWU9Ik5tUG9seWdvbiIgQWxpYXM9IuefqeW9oui+ueeVjCIgSWNvbj0iTm1SZWN0YW5nbGUiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI1MTA1IiBCb3VuZHM9IjEsNSIgTmFtZT0iTm1Qb2x5Z29uIiBBbGlhcz0i5ZyG5b2i6L6555WMIiBJY29uPSJObVJvdW5kIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iNTEwNiIgQm91bmRzPSIwLDYsMiwxIiBOYW1lPSJObUZhdWx0IiBBbGlhcz0i5pat5bGCIiBJY29uPSJObUZhdWx0IiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iNTEwNyIgQm91bmRzPSIwLDciIE5hbWU9Ik5tV2VsbCIgQWxpYXM9IumAieaLqeS6lSIgSWNvbj0iTm1XZWxsIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iNTEwOCIgQm91bmRzPSIxLDciIE5hbWU9Ik5tV2VsbCIgQWxpYXM9IuaWsOW7uuS6lSIgSWNvbj0iTm1XZWxsIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iNTEwOSIgQm91bmRzPSIwLDgsMiwxIiBOYW1lPSJObUZhdWx0IiBBbGlhcz0i6KOC57ydIiBJY29uPSJObUZhdWx0IiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iNTExMCIgQm91bmRzPSIwLDkiIE5hbWU9Ik5tTGltaXQiIEFsaWFzPSLljLrln58iIEljb249Ik5tTGltaXQiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI1MTExIiBCb3VuZHM9IjEsOSIgTmFtZT0iTm1SZWdpb24iIEFsaWFzPSLmoIforrDljLrln58iIEljb249Ik5tUmVnaW9uIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iNTEyMSIgQm91bmRzPSIwLDEwLDIsMSIgTmFtZT0iTm1EZWxldGUiIEFsaWFzPSLliKDpmaQiIEljb249Ik5tRGVsZXRlIiAvPg0KICAgICAgIDwvR3JvdXA+DQoNCiAgICAgICA8R3JvdXAgTmFtZT0iTnRSZXNlcnZvaXIiIEFsaWFzPSLlgqjlsYLnibnlvoEiPgogICAgICAgICAgICA8Q21kIElEPSI1MTEyIiBCb3VuZHM9IjAsMCwyLDEiIE5hbWU9Ik5tR2VvbWV0cnkiIEFsaWFzPSLliIblsYIiIEljb249Ik5tR2VvbWV0cnkiIC8+CiAgICAgICAgICAgIDxDbWQgSUQ9IjUxMTMiIEJvdW5kcz0iMCwxLDIsMSIgTmFtZT0iTm1Qcm9wZXJ0aWVzIiBBbGlhcz0i5YKo5bGC54m55oCnIiBJY29uPSJObVByb3BlcnRpZXMiIC8+CiAgICAgICAgICAgIDxDbWQgSUQ9IjUxMjIiIEJvdW5kcz0iMCwyLDIsMSIgTmFtZT0iTm1ERk4iIEFsaWFzPSJERk4iIEljb249Ik5tREZOIiAvPgogICAgICAgICAgICA8Q21kIElEPSI1MTI2IiBCb3VuZHM9IjAsMywyLDEiIE5hbWU9Ik5tSW50ZXJwb2xhdGlvbiIgQWxpYXM9IuWxnuaAp+aPkuWAvCIgSWNvbj0iTm1JbnRlcnBvbGF0aW9uIiAvPgogICAgICAgPC9Hcm91cD4KDQogICAgICAgPEdyb3VwIE5hbWU9Ik50TW9kZWwiIEFsaWFzPSLmqKHlnovnlJ/miJAiPg0KICAgICAgICAgICAgIDxDbWQgSUQ9IjUxMTQiIEJvdW5kcz0iMCwwLDIsMSIgTmFtZT0iTm1HcmlkIiBBbGlhcz0i572R5qC85YiS5YiGIiBJY29uPSJObUdyaWQiIC8+DQogICAgICAgICAgICAgPENtZCBJRD0iNTExNSIgQm91bmRzPSIwLDEsMiwxIiBOYW1lPSJObUNhY3VsYXRpb24iIEFsaWFzPSLorqHnrpfmsYLop6MiIEljb249IlRpbWUiIC8+DQogICAgICAgICAgICAgPCEtLQ0KICAgICAgICAgICAgIDxDbWQgSUQ9IjUxMTYiIEJvdW5kcz0iMCwyLDIsMSIgTmFtZT0iTm1CYWNrIiBBbGlhcz0i5ZCO5aSE55CGIiBJY29uPSJUaW1lIiAvPg0KICAgICAgICAgICAgIDxDbWQgSUQ9IjUxMTciIEJvdW5kcz0iMCwzLDIsMSIgTmFtZT0iTm1SZXN1bHQiIEFsaWFzPSLnu5PmnpwiIEljb249IkZsb3dQZXJpb2QiIC8+DQogICAgICAgICAgICAgLS0+DQogICAgICAgPC9Hcm91cD4NCg0KICAgICAgICA8R3JvdXAgTmFtZT0iTnRUb29scyIgQWxpYXM9IuW3peWFtyI+DQogICAgICAgICAgICA8Q21kIElEPSI1MTI3IiBCb3VuZHM9IjAsMCIgTmFtZT0iTm1HZW9SZWZlcmVuY2UiIEFsaWFzPSLmqKHlnovlj4LogIPngrnorr7nva4iIEljb249Ik5tR2VvUmVmZXJlbmNlIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iNTEyOCIgQm91bmRzPSIxLDAiIE5hbWU9Ik5tUG9pbnRlclBvc2l0aW9uIiBBbGlhcz0i5qih5Z6L5L2N572u5pi+56S6IiBJY29uPSJObVBvaW50ZXJQb3NpdGlvbiIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjUxMjkiIEJvdW5kcz0iMCwxLDIsMSIgTmFtZT0iTm1NZWFzdXJlIiBBbGlhcz0i5qih5Z6L5bC65a+45rWL6YePIiBJY29uPSJObU1lYXN1cmUiIC8+DQogICAgICAgPC9Hcm91cD4NCg0KICAgICAgICA8R3JvdXAgTmFtZT0iTnREaXNwbGF5IiBBbGlhcz0i5pi+56S6Ij4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjUxMjMiIEJvdW5kcz0iMCwwLDIsMSIgTmFtZT0iTm1TaG93IiBBbGlhcz0i5pi+56S6IiBJY29uPSJObVNob3ciIC8+DQogICAgICAgICAgICA8Q21kIElEPSI1MTI0IiBCb3VuZHM9IjAsMSwyLDEiIE5hbWU9Ik5tUHJpbnRQcmV2aWV3IiBBbGlhcz0i5omT5Y2w6aKE6KeIIiBJY29uPSJObVByaW50UHJldmlldyIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjUxMjUiIEJvdW5kcz0iMCwyLDIsMSIgTmFtZT0iTm1QcmludCIgQWxpYXM9IuaJk+WNsCIgSWNvbj0iTm1QcmludCIgLz4NCiAgICAgICA8L0dyb3VwPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJXaW5kb3ciIEFsaWFzPSLnqpflj6PmmL7npLoiICBWaXNpYmxlPSIwIj4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkwMDIiIEJvdW5kcz0iMCwwIiBOYW1lPSJWaXNpYmxlTW9kZWxzIiBBbGlhcz0i5qih5Z6L56qX5Y+jIiBJY29uPSJWaXNpYmxlTW9kZWxzIiAgVmlzaWJsZT0iMCIvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTAwMyIgQm91bmRzPSIxLDAiIE5hbWU9IlZpc2libGVQYXJhbWV0ZXJzIiBBbGlhcz0i5Y+C5pWw56qX5Y+jIiBJY29uPSJWaXNpYmxlUGFyYW1ldGVycyIgIFZpc2libGU9IjAiLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkxMDEiIEJvdW5kcz0iMCwxIiBOYW1lPSJWaXNpYmxlQW5hbEJhc2ljIiBBbGlhcz0i5Z+656GA5L+h5oGvIiBJY29uPSJJbnB1dEJhc2ljIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTEwMiIgQm91bmRzPSIxLDEiIE5hbWU9IlZpc2libGVBbmFsUFZUIiBBbGlhcz0iUFZU5pWw5o2uIiBJY29uPSJJbnB1dEZsdWlkIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTEwMyIgQm91bmRzPSIwLDIiIE5hbWU9IlZpc2libGVBbmFsRGlmZiIgQWxpYXM9IkRJRkbmlbDmja4iIEljb249IklucHV0Rmx1aWQiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI5MTA0IiBCb3VuZHM9IjEsMiIgTmFtZT0iVmlzaWJsZUFuYWxQc2V1IiBBbGlhcz0i5ouf5Y6L5Yqb5pWw5o2uIiBJY29uPSJJbnB1dEZsdWlkIiAvPg0KICAgICAgICA8L0dyb3VwPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJObURlYnVnIiBBbGlhcz0i5qGG5p625rWL6K+VKERlYnVnKSI+DQogICAgICAgICAgICA8Q21kIElEPSI1OTk5IiBCb3VuZHM9IjAsMCwyLDEiIE5hbWU9Ik5tRGVidWciIEFsaWFzPSLmoYbmnrbku6PnoIHosIPor5UiIEljb249IlByZXBhcmVHcmlkIiAvPg0KICAgICAgICA8L0dyb3VwPg0KDQoNCiAgICA8L1RhYj4NCg0KICAgIDxUYWIgSUQ9IjQiIE5hbWU9Ik1pbmlGcmFjIiBBbGlhcz0i5bCP5Z6L5Y6L6KOCKEYpKERlYnVnKSIgPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJBbmFsRWRpdCIgQWxpYXM9IuWIhuaekOeuoeeQhiI+DQogICAgICAgICAgICA8Q21kIElEPSIzMDA2IiBCb3VuZHM9IjAsMCIgTmFtZT0iQW5hbE5ldyIgQWxpYXM9IuaWsOW7uuWIhuaekCIgSWNvbj0iSm9iTmV3IiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMzAwNyIgQm91bmRzPSIxLDAiIE5hbWU9IkFuYWxFZGl0IiBBbGlhcz0i5YiG5p6Q566h55CGIiBJY29uPSJKb2JFZGl0IiAvPg0KICAgICAgICA8L0dyb3VwPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJQQSIgQWxpYXM9IuWOi+mZjeWIhuaekCI+DQogICAgICAgICAgICA8Q21kIElEPSI0MDAyIiBCb3VuZHM9IjAsMCwzLDEiIE5hbWU9Ik1pbmlGckFuYWxQQSIgQWxpYXM9IuWOi+mZjeWHhuWkhyIgRXh0SW5mbz0iUEYiIEljb249IlBGIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iNDAwMyIgQm91bmRzPSIwLDEsMywxIiBOYW1lPSJNaW5pRnJQQSIgQWxpYXM9IuWOi+mZjeWIhuaekCIgSWNvbj0iRmxvd1BlcmlvZCIgLz4NCg0KICAgICAgICAgICAgPENtZCBJRD0iNDAwNCIgQm91bmRzPSIwLDIsMywxIiBOYW1lPSJDYWxTdWRkZW5TdG9wUCIgQWxpYXM9IueerOaXtuWBnOazteWOi+WKmyIgSWNvbj0iUnVuRXgiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI0MDA1IiBCb3VuZHM9IjAsMyIgTmFtZT0iQ2FsR0Z1bmN0aW9uIiBBbGlhcz0iR+WHveaVsCIgSWNvbj0iUnVuT3RoZXIiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI0MDA2IiBCb3VuZHM9IjEsMyIgTmFtZT0iQ2FsU3FydFQiIEFsaWFzPSLml7bpl7TlubPmlrnmoLkiIEljb249IlJ1bk90aGVyIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iNDAwNyIgQm91bmRzPSIyLDMiIE5hbWU9IkNhbExvZ0xvZyIgQWxpYXM9IuWPjOWvueaVsCIgSWNvbj0iUnVuT3RoZXIiIC8+DQogICAgICAgIDwvR3JvdXA+DQoNCg0KICAgICAgICA8R3JvdXAgTmFtZT0iRkEiIEFsaWFzPSLmjpLph4/liIbmnpAiPg0KICAgICAgICAgICAgPENtZCBJRD0iNDEwMiIgQm91bmRzPSIwLDAsMiwxIiBOYW1lPSJNaW5pRnJBbmFsRkEiIEFsaWFzPSLmjpLph4/lh4blpIciIEV4dEluZm89IklQUiIgSWNvbj0iTWluaUZyQW5hbEZBIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iNDEwMyIgQm91bmRzPSIwLDEiIE5hbWU9Ik1pbmlGckZBVXAiIEFsaWFzPSLpmLbmoq/ljYciIEljb249IlN0ZXBVcCIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjQxMDQiIEJvdW5kcz0iMSwxIiBOYW1lPSJNaW5pRnJGQURvd24iIEFsaWFzPSLpmLbmoq/pmY0iIEljb249IlN0ZXBEb3duIiAvPg0KICAgICAgIDwvR3JvdXA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9IkpvYnMiIEFsaWFzPSLmiJDmnpznrqHnkIYiICBWaXNpYmxlPSIwIj4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjEwMDgiIEJvdW5kcz0iMCwwIiBOYW1lPSJSc3RMb2FkIiBBbGlhcz0i5Yqg6L295oiQ5p6cIiBJY29uPSJMb2FkSm9icyIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjEwMDkiIEJvdW5kcz0iMSwwIiBOYW1lPSJSc3RTYXZlIiBUeXBlPSIxIiBFeHROYW1lcz0iUnN0U2F2ZUN1cjtSc3RTYXZlQWxsIiBFeHRJbmZvPSLkv53lrZjlvZPliY3miJDmnpw75L+d5a2Y5omA5pyJ5oiQ5p6cIiBBbGlhcz0i5L+d5a2Y5oiQ5p6cIiBJY29uPSJTYXZlSm9icyIgLz4NCiAgICAgICAgPC9Hcm91cD4NCg0KICAgICAgICA8R3JvdXAgTmFtZT0iV2luZG93IiBBbGlhcz0i56qX5Y+j5pi+56S6IiAgVmlzaWJsZT0iMCI+DQogICAgICAgICAgICA8Q21kIElEPSI5MDAyIiBCb3VuZHM9IjAsMCIgTmFtZT0iVmlzaWJsZU1vZGVscyIgQWxpYXM9IuaooeWei+eql+WPoyIgSWNvbj0iVmlzaWJsZU1vZGVscyIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkwMDMiIEJvdW5kcz0iMSwwIiBOYW1lPSJWaXNpYmxlUGFyYW1ldGVycyIgQWxpYXM9IuWPguaVsOeql+WPoyIgSWNvbj0iVmlzaWJsZVBhcmFtZXRlcnMiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI5MTAxIiBCb3VuZHM9IjAsMSIgTmFtZT0iVmlzaWJsZUFuYWxCYXNpYyIgQWxpYXM9IuWfuuehgOS/oeaBryIgSWNvbj0iSW5wdXRCYXNpYyIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkxMDIiIEJvdW5kcz0iMSwxIiBOYW1lPSJWaXNpYmxlQW5hbFBWVCIgQWxpYXM9IlBWVOaVsOaNriIgSWNvbj0iSW5wdXRGbHVpZCIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkxMDMiIEJvdW5kcz0iMCwyIiBOYW1lPSJWaXNpYmxlQW5hbERpZmYiIEFsaWFzPSJESUZG5pWw5o2uIiBJY29uPSJJbnB1dEZsdWlkIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTEwNCIgQm91bmRzPSIxLDIiIE5hbWU9IlZpc2libGVBbmFsUHNldSIgQWxpYXM9IuaLn+WOi+WKm+aVsOaNriIgSWNvbj0iSW5wdXRGbHVpZCIgLz4NCiAgICAgICAgPC9Hcm91cD4NCg0KICAgIDwvVGFiPg0KDQogICAgPFRhYiBJRD0iNDAxIiBOYW1lPSJXRFQiIEFsaWFzPSLkuqfog73or5XkupUoUCkiID4NCg0KICAgICAgICA8R3JvdXAgTmFtZT0iQW5hbEVkaXQiIEFsaWFzPSLliIbmnpDnrqHnkIYiPg0KICAgICAgICAgICAgPENtZCBJRD0iMzAwNiIgQm91bmRzPSIwLDAiIE5hbWU9IkFuYWxOZXciIEFsaWFzPSLmlrDlu7rliIbmnpAiIEljb249IkpvYk5ldyIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjMwMDciIEJvdW5kcz0iMSwwIiBOYW1lPSJBbmFsRWRpdCIgQWxpYXM9IuWIhuaekOeuoeeQhiIgSWNvbj0iSm9iRWRpdCIgLz4NCiAgICAgICAgPC9Hcm91cD4NCg0KICAgICAgICA8R3JvdXAgTmFtZT0iSVBSIiBBbGlhcz0iSVBS5YWI5YmN5Y+C6ICDKERlYnVnKSI+DQogICAgICAgICAgICA8Q21kIElEPSI2MDAyIiBCb3VuZHM9IjAsMCwyLDEiIE5hbWU9IklQUkFuYWwiIEFsaWFzPSJJUFLlh4blpIciIEV4dEluZm89IklQUiIgSWNvbj0iSVBSQW5hbCIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjYwMDMiIEJvdW5kcz0iMCwxLDIsMSIgTmFtZT0iSVBSQ2FsIiBBbGlhcz0iSVBS6K6h566XIiBJY29uPSJJUFJDYWwiIC8+DQogICAgICAgIDwvR3JvdXA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9IldkdERhdGFQcmVwcm9jZXNzIiBBbGlhcz0i5pWw5o2u6aKE5aSE55CGIiBWaXNpYmxlPSIwIj4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjYxMDEiIEJvdW5kcz0iMCwwLDIsMSIgTmFtZT0iV2R0RGF0YUFzc24iIEFsaWFzPSLmlbDmja7lvZLkuIDljJYiIEV4dEluZm89IldEVCIgSWNvbj0iSVBSQW5hbCIgIFZpc2libGU9IjAiLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjYxMDIiIEJvdW5kcz0iMCwxLDIsMSIgTmFtZT0iV2R0T3RoZXIiIEFsaWFzPSLlhbblroMiIEljb249IldkdE90aGVyIiBWaXNpYmxlPSIwIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iNjEwMyIgQm91bmRzPSIwLDMsMiwxIiBOYW1lPSJXZHRXTUYiIEFsaWFzPSLkupXnrZLlpJrnm7jmtYEiIEljb249IldkdFdNRiIgIFZpc2libGU9IjAiLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjYxMDQiIEJvdW5kcz0iMCw0LDIsMSIgTmFtZT0iV2R0Q2hva2UiIEFsaWFzPSLlmLTmtYEiIEljb249IldkdENob2tlIiAgVmlzaWJsZT0iMCIvPg0KICAgICAgICA8L0dyb3VwPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJJUFIiIEFsaWFzPSLkuqfog73liIbmnpAiPg0KICAgICAgICAgICAgPENtZCBJRD0iNjIwMSIgQm91bmRzPSIwLDAsMiwxIiBOYW1lPSJXZHRJUFJDYWwiIEV4dEluZm89IldEVCIgQWxpYXM9IuWCqOWxguS6p+iDveiuoeeulyIgSWNvbj0iSVBSQ2FsIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iNjIwMiIgQm91bmRzPSIwLDEsMiwxIiBOYW1lPSJXZWxsUGR0eSIgQWxpYXM9IuS4gOS9k+WMluS6p+iDvSIgSWNvbj0iV2VsbFBkdHkiICBWaXNpYmxlPSIwIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iNjIwMyIgQm91bmRzPSIwLDIsMiwxIiBOYW1lPSJXZHRJUFJFeHQiIEFsaWFzPSLkuqfog73or5XkupVb5omp5bGVXSIgSWNvbj0iSVBSRXh0Ii8+DQogICAgICAgICAgICA8Q21kIElEPSI2MjA0IiBCb3VuZHM9IjAsMywyLDEiIE5hbWU9IldkdElQUkFuYWwiIEFsaWFzPSLlgqjlsYLkuqfog73liIbmnpAiIEljb249IklQUkFuYWwiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI2MjA1IiBCb3VuZHM9IjAsNCwyLDEiIE5hbWU9IldlbGxJbnRlZ0FuYWwiIEFsaWFzPSLnu7zlkIjliIbmnpAiIEljb249IldlbGxJbnRlZ0FuYWwiIFZpc2libGU9IjAiIC8+DQogICAgICAgIDwvR3JvdXA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9IklQUiIgQWxpYXM9IuS6p+iDveiuoeeulyI+DQogICAgICAgICAgICA8Q21kIElEPSI2MzAxIiBCb3VuZHM9IjAsMCwyLDEiIE5hbWU9IldkdENhbCIgQWxpYXM9IuiuoeeulyIgRXh0SW5mbz0iV0RUIiBJY29uPSJSdW5FeCIgLz4NCiAgICAgICAgPC9Hcm91cD4NCg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJKb2JzIiBBbGlhcz0i5oiQ5p6c566h55CGIj4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjEwMDgiIEJvdW5kcz0iMCwwIiBOYW1lPSJSc3RMb2FkIiBBbGlhcz0i5Yqg6L295oiQ5p6cIiBJY29uPSJMb2FkSm9icyIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjEwMDkiIEJvdW5kcz0iMSwwIiBOYW1lPSJSc3RTYXZlIiBUeXBlPSIxIiBFeHROYW1lcz0iUnN0U2F2ZUN1cjtSc3RTYXZlQWxsIiBFeHRJbmZvPSLkv53lrZjlvZPliY3miJDmnpw75L+d5a2Y5omA5pyJ5oiQ5p6cIiBBbGlhcz0i5L+d5a2Y5oiQ5p6cIiBJY29uPSJTYXZlSm9icyIgLz4NCiAgICAgICAgPC9Hcm91cD4NCg0KICAgICAgICA8R3JvdXAgTmFtZT0iV2luZG93IiBBbGlhcz0i56qX5Y+j5pi+56S6Ij4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkwMDIiIEJvdW5kcz0iMCwwIiBOYW1lPSJWaXNpYmxlTW9kZWxzIiBBbGlhcz0i5qih5Z6L56qX5Y+jIiBJY29uPSJWaXNpYmxlTW9kZWxzIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTAwMyIgQm91bmRzPSIxLDAiIE5hbWU9IlZpc2libGVQYXJhbWV0ZXJzIiBBbGlhcz0i5Y+C5pWw56qX5Y+jIiBJY29uPSJWaXNpYmxlUGFyYW1ldGVycyIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkxMDEiIEJvdW5kcz0iMCwxIiBOYW1lPSJWaXNpYmxlQW5hbEJhc2ljIiBBbGlhcz0i5Z+656GA5L+h5oGvIiBJY29uPSJJbnB1dEJhc2ljIiAgIFZpc2libGU9IjAiLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkxMDIiIEJvdW5kcz0iMCwxIiBOYW1lPSJWaXNpYmxlQW5hbFBWVCIgQWxpYXM9IlBWVOaVsOaNriIgSWNvbj0iSW5wdXRGbHVpZCIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkxMDMiIEJvdW5kcz0iMCwyIiBOYW1lPSJWaXNpYmxlQW5hbERpZmYiIEFsaWFzPSJESUZG5pWw5o2uIiBJY29uPSJJbnB1dEZsdWlkIiAgIFZpc2libGU9IjAiLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkxMDQiIEJvdW5kcz0iMSwxIiBOYW1lPSJWaXNpYmxlQW5hbFBzZXUiIEFsaWFzPSLmi5/ljovlipvmlbDmja4iIEljb249IklucHV0Rmx1aWQiIC8+DQogICAgICAgIDwvR3JvdXA+DQoNCg0KICAgIDwvVGFiPg0KDQogICAgPFRhYiBJRD0iNiIgTmFtZT0iQWR2YW5jZWRGdW5jdGlvbiIgQWxpYXM9IuivleS6leiuvuiuoShYKSIgPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJEZXNpZ24iIEFsaWFzPSLor5XkupXorr7orqEiPg0KICAgICAgICAgICAgPENtZCBJRD0iNjAwMSIgQm91bmRzPSIwLDAsMiwxIiBOYW1lPSJUZXN0RGVzaWduIiBBbGlhcz0i6K+V5LqV6K6+6K6hIiBJY29uPSJUZXN0RGVzaWduIiBFeHRJbmZvPSJQRiIgIC8+DQogICAgICAgICAgICA8Q21kIElEPSIzMDA0IiBCb3VuZHM9IjAsMSwyLDEiIE5hbWU9IkFuYWxGbG93U2VnIiBBbGlhcz0i5rWB5Yqo5q615YiG5p6QIiBJY29uPSJGbG93UGVyaW9kIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMzAwNSIgQm91bmRzPSIwLDIsMiwxIiBOYW1lPSJBbmFsT3RoZXJzIiBBbGlhcz0i54m55b6B5q615YiG5p6QIiBUeXBlPSIxIiBFeHROYW1lcz0iQ2hhcnRUO0NoYXJ0U3FydFQ7Q2hhcnQyNVQ7Q2hhcnQ1VCIgRXh0SW5mbz0iQ2hhcnQgVDtDaGFydCBTcXJ0KFQpO0NoYXJ0IDAuMjVUO0NoYXJ0IC0wLjVUIiBJY29uPSJBc3Npc0FuYWwiIC8+DQogICAgICAgICAgICA8Q21kIElEPSIzMDA5IiBCb3VuZHM9IjAsMywyLDEiIE5hbWU9IkFuYWxEaXN0cmkiIEFsaWFzPSLliIbluIPlm74iIFR5cGU9IjEiIEV4dE5hbWVzPSJDaGFydERlbjtDaGFydFZpcyIgRXh0SW5mbz0i5rWT5bqm5YiG5biD5Zu+O+m7j+W6puWIhuW4g+WbviIgSWNvbj0iQW5hbERpc3RyaSIgLz4NCg0KICAgICAgICA8L0dyb3VwPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJEYXRhRml0IiBBbGlhcz0i6Kej6YeK5ouf5ZCIIj4NCg0KICAgICAgICAgICAgPENtZCBJRD0iMzEwNSIgQm91bmRzPSIwLDAsMiwxIiBOYW1lPSJEZWNvbnZvbHYiIEFsaWFzPSLlj43opLbnp68iIEljb249IkRlY29udm9sdiIgVmlzaWJsZT0iMCIvPg0KICAgICAgICAgICAgPENtZCBJRD0iMzEwMSIgQm91bmRzPSIwLDEsMiwxIiBOYW1lPSJGaXRNb2RlbCIgQWxpYXM9Iuino+aekOinoyIgSWNvbj0iRml0TW9kZWwiIC8+DQogICAgICAgICAgICA8Q21kIElEPSIzMTA0IiBCb3VuZHM9IjAsMiwyLDEiIE5hbWU9Im5tRml0TW9kZWwiIEFsaWFzPSLmlbDlgLzop6MiIEljb249IkZpdE1vZGVsIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMzEwMiIgQm91bmRzPSIwLDMsMiwxIiBOYW1lPSJBdXRvRml0IiBBbGlhcz0i6Ieq5Yqo5ouf5ZCIIiBJY29uPSJBdXRvRml0IiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMzEwMyIgQm91bmRzPSIwLDQsMiwxIiBOYW1lPSJQbGF0ZUZpdCIgQWxpYXM9IuaVj+aEn+aAp+WIhuaekCIgSWNvbj0iUGxhdGVGaXQiIC8+DQogICAgICAgPC9Hcm91cD4NCg0KICAgICAgICA8R3JvdXAgTmFtZT0iQUlUZXN0IiBBbGlhcz0i5pm66IO96K+V5LqVKERlYnVnKSI+DQogICAgICAgICAgICA8Q21kIElEPSIzOTAxIiBCb3VuZHM9IjAsMCwyLDEiIE5hbWU9Ik1vZGVsQ2xhc3NpZnkiIEFsaWFzPSLmqKHlnovor4bliKsiIEljb249Ik1vZGVsQ2xhc3NpZnkiIC8+DQogICAgICAgIDwvR3JvdXA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9IlJlbGF0aXZlVG9vbCIgQWxpYXM9IuebuOWFs+W3peWFtyIgVmlzaWJsZT0iMCI+DQogICAgICAgICAgICA8Q21kIElEPSIzMjAxIiBCb3VuZHM9IjAsMCIgTmFtZT0iVGltZSIgQWxpYXM9IuaXtumXtCIgSWNvbj0iVGltZSIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjMyMDIiIEJvdW5kcz0iMSwwIiBOYW1lPSJTaG93TW9kZWxDaGFydHMiIEFsaWFzPSLmqKHlnosiIEljb249IlNob3dNb2RlbENoYXJ0cyIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjMyMDMiIEJvdW5kcz0iMCwxIiBOYW1lPSJTaG93TW9kZWxTa2V0Y2giIEFsaWFzPSLnkIborroiIEljb249IlNob3dNb2RlbFNrZXRjaCIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjMyMDQiIEJvdW5kcz0iMSwxIiBOYW1lPSJTYXZlQXNNb2RlbFNrZXRjaCIgQWxpYXM9IuWtmOS4uuekuuaEjyIgSWNvbj0iU2F2ZUFzTW9kZWxTa2V0Y2giIC8+ICAgICAgICAgICAgDQogICAgICAgPC9Hcm91cD4NCg0KICAgICAgICA8R3JvdXAgTmFtZT0iVG9vbFMiIEFsaWFzPSLmianlsZXlip/og70iICBWaXNpYmxlPSIwIj4NCiAgICAgICAgICAgIDxDbWQgSUQ9Ijk4MDEiIEJvdW5kcz0iMCwwLDIsMSIgTmFtZT0iRmxvd1RvUyIgQWxpYXM9Iua1gemHj+WPmOihqOeariIgSWNvbj0iRmxvd1RvUyIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkyMDEiIEJvdW5kcz0iMCwxLDIsMSIgTmFtZT0iTWl4VmlzY29zaXR5IiBBbGlhcz0i5re35ZCI6buP5bqmIiBJY29uPSJNaXhWaXNjb3NpdHkiIC8+DQogICAgICAgPC9Hcm91cD4NCg0KICAgICAgICA8R3JvdXAgTmFtZT0iSm9icyIgQWxpYXM9IuaIkOaenOeuoeeQhiIgVmlzaWJsZT0iMCI+DQogICAgICAgICAgICA8Q21kIElEPSIxMDA4IiBCb3VuZHM9IjAsMCIgTmFtZT0iUnN0TG9hZCIgQWxpYXM9IuWKoOi9veaIkOaenCIgSWNvbj0iTG9hZEpvYnMiIC8+DQogICAgICAgICAgICA8Q21kIElEPSIxMDA5IiBCb3VuZHM9IjEsMCIgTmFtZT0iUnN0U2F2ZSIgVHlwZT0iMSIgRXh0TmFtZXM9IlJzdFNhdmVDdXI7UnN0U2F2ZUFsbCIgRXh0SW5mbz0i5L+d5a2Y5b2T5YmN5oiQ5p6cO+S/neWtmOaJgOacieaIkOaenCIgQWxpYXM9IuS/neWtmOaIkOaenCIgSWNvbj0iU2F2ZUpvYnMiIC8+DQogICAgICAgIDwvR3JvdXA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9IldpbmRvdyIgQWxpYXM9Iueql+WPo+aYvuekuiIgVmlzaWJsZT0iMCI+DQogICAgICAgICAgICA8Q21kIElEPSI5MDAyIiBCb3VuZHM9IjAsMCIgTmFtZT0iVmlzaWJsZU1vZGVscyIgQWxpYXM9IuaooeWei+eql+WPoyIgSWNvbj0iVmlzaWJsZU1vZGVscyIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkwMDMiIEJvdW5kcz0iMSwwIiBOYW1lPSJWaXNpYmxlUGFyYW1ldGVycyIgQWxpYXM9IuWPguaVsOeql+WPoyIgSWNvbj0iVmlzaWJsZVBhcmFtZXRlcnMiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI5MTAxIiBCb3VuZHM9IjAsMSIgTmFtZT0iVmlzaWJsZUFuYWxCYXNpYyIgQWxpYXM9IuWfuuehgOS/oeaBryIgSWNvbj0iSW5wdXRCYXNpYyIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkxMDIiIEJvdW5kcz0iMSwxIiBOYW1lPSJWaXNpYmxlQW5hbFBWVCIgQWxpYXM9IlBWVOaVsOaNriIgSWNvbj0iSW5wdXRGbHVpZCIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkxMDMiIEJvdW5kcz0iMCwyIiBOYW1lPSJWaXNpYmxlQW5hbERpZmYiIEFsaWFzPSJESUZG5pWw5o2uIiBJY29uPSJJbnB1dEZsdWlkIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTEwNCIgQm91bmRzPSIxLDIiIE5hbWU9IlZpc2libGVBbmFsUHNldSIgQWxpYXM9IuaLn+WOi+WKm+aVsOaNriIgSWNvbj0iSW5wdXRGbHVpZCIgLz4NCiAgICAgICAgPC9Hcm91cD4NCg0KICAgIDwvVGFiPg0KDQogICAgPFRhYiBJRD0iNyIgTmFtZT0iQWlUZXN0IiBBbGlhcz0i5pm66IO96K+V5LqVKEkpIj4NCg0KICAgICAgICA8R3JvdXAgTmFtZT0iRGVtbzEiIEFsaWFzPSLmoLfkvovoj5zljZUxIj4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjcwMDEiIEJvdW5kcz0iMCwwLDIsMSIgTmFtZT0iQWN0aW9uTmFtZTEiIEFsaWFzPSLkuLTml7bmtYvor5UxIiBJY29uPSJUT0RPMSIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjcwMDIiIEJvdW5kcz0iMCwxLDIsMSIgTmFtZT0iQWN0aW9uTmFtZTIiIEFsaWFzPSLkuLTml7bmtYvor5UyIiBJY29uPSJUT0RPMiIgLz4NCiAgICAgICAgPC9Hcm91cD4NCg0KICAgICAgICA8R3JvdXAgTmFtZT0iRGVtbzIiIEFsaWFzPSLmoLfkvovoj5zljZUyIj4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjcxMDEiIEJvdW5kcz0iMCwwLDIsMSIgTmFtZT0iQWN0aW9uTmFtZTMiIEFsaWFzPSLkuLTml7bmtYvor5UzIiBJY29uPSJUT0RPMyIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjcxMDIiIEJvdW5kcz0iMCwxLDIsMSIgTmFtZT0iQWN0aW9uTmFtZTQiIEFsaWFzPSLkuLTml7bmtYvor5U0IiBJY29uPSJUT0RPNCIgLz4NCiAgICAgICAgPC9Hcm91cD4NCg0KICAgICAgICA8R3JvdXAgTmFtZT0iRGVtbzMiIEFsaWFzPSLmoLfkvovoj5zljZUzIj4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjcyMDEiIEJvdW5kcz0iMCwwLDIsMSIgTmFtZT0iQWN0aW9uTmFtZTQiIEFsaWFzPSLkuLTml7bmtYvor5U1IiBJY29uPSJUT0RPNSIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjcyMDIiIEJvdW5kcz0iMCwxLDIsMSIgTmFtZT0iQWN0aW9uTmFtZTUiIEFsaWFzPSLkuLTml7bmtYvor5U2IiBJY29uPSJUT0RPNiIgLz4NCiAgICAgICAgPC9Hcm91cD4NCg0KICAgICAgICA8R3JvdXAgTmFtZT0iTm1EZWJ1ZyIgQWxpYXM9Iuahhuaetua1i+ivlShEZWJ1ZykiPg0KICAgICAgICAgICAgPENtZCBJRD0iNzk5OSIgQm91bmRzPSIwLDAsMiwxIiBOYW1lPSJObURlYnVnIiBBbGlhcz0i5qGG5p625Luj56CB6LCD6K+VIiBJY29uPSJQcmVwYXJlR3JpZCIgLz4NCiAgICAgICAgPC9Hcm91cD4NCg0KDQoNCiAgICA8L1RhYj4NCg0KICAgIDxUYWIgSUQ9IjgiIE5hbWU9IlJlc3VsdCIgQWxpYXM9IuaIkOaenOeuoeeQhihSKSIgPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJKb2JzIiBBbGlhcz0i5oiQ5p6c566h55CGIj4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjEwMDgiIEJvdW5kcz0iMCwwIiBOYW1lPSJSc3RMb2FkIiBBbGlhcz0i5Yqg6L295oiQ5p6cIiBJY29uPSJMb2FkSm9icyIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjEwMDkiIEJvdW5kcz0iMSwwIiBOYW1lPSJSc3RTYXZlIiBUeXBlPSIxIiBFeHROYW1lcz0iUnN0U2F2ZUN1cjtSc3RTYXZlQWxsIiBFeHRJbmZvPSLkv53lrZjlvZPliY3miJDmnpw75L+d5a2Y5omA5pyJ5oiQ5p6cIiBBbGlhcz0i5L+d5a2Y5oiQ5p6cIiBJY29uPSJTYXZlSm9icyIgLz4NCiAgICAgICAgPC9Hcm91cD4NCg0KICAgICAgICA8R3JvdXAgTmFtZT0iUmVzQ29tcGFyZSIgQWxpYXM9IuaIkOaenOWvueavlCI+DQogICAgICAgICAgICA8Q21kIElEPSI4MDAzIiBCb3VuZHM9IjAsMCwyLDEiIE5hbWU9IlJlc0NvbXBhcmUiIEFsaWFzPSLmiJDmnpzlr7nmr5QiIEljb249IlJlc0NvbXBhcmUiICAvPg0KICAgICAgICA8L0dyb3VwPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJQcmludCIgQWxpYXM9IuaKpeWRiuaJk+WNsCI+DQogICAgICAgICAgICA8Q21kIElEPSI4MDAxIiBCb3VuZHM9IjAsMCIgTmFtZT0iUmVwb3J0Q29uZmlnIiBBbGlhcz0i5oql5ZGK6K6+572uIiBJY29uPSJyZXBvcnRDb25maWciICAvPg0KICAgICAgICAgICAgPENtZCBJRD0iODAwNCIgQm91bmRzPSIxLDAiIE5hbWU9IlByaW50UHJldmlldyIgQWxpYXM9IuaKpeWRiumihOiniCIgSWNvbj0iUHJlUHJpbnQiICAvPg0KICAgICAgICAgICAgPENtZCBJRD0iODAwMiIgQm91bmRzPSIwLDEiIE5hbWU9IlByaW50IiBBbGlhcz0i5omT5Y2wKOWQq1BERikiIEljb249IlByaW50IiAgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjgwMDUiIEJvdW5kcz0iMSwxIiBOYW1lPSJFeHBvcnRXb3JkIiBBbGlhcz0i5a+85Ye6KFdvcmQpIiBJY29uPSJXb3JkMTYiICAvPg0KICAgICAgICA8L0dyb3VwPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJXaW5kb3ciIEFsaWFzPSLnqpflj6PmmL7npLoiIFZpc2libGU9IjAiPg0KICAgICAgICAgICAgPENtZCBJRD0iOTAwMyIgQm91bmRzPSIwLDAsMiwxIiBOYW1lPSJWaXNpYmxlUGFyYW1ldGVycyIgQWxpYXM9IuWPguaVsOeql+WPoyIgSWNvbj0iVmlzaWJsZVBhcmFtZXRlcnMiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI5MDA0IiBCb3VuZHM9IjAsMSwyLDEiIE5hbWU9IlZpc2libGVQdHlzIiBBbGlhcz0i5bGe5oCn56qX5Y+jIiBJY29uPSJQcm9wZXJ0eVdpbmRvdyIgLz4NCg0KICAgICAgICA8L0dyb3VwPg0KDQogICAgPC9UYWI+DQoNCiAgICA8VGFiIElEPSI5IiBOYW1lPSJXaW5kb3ciIEFsaWFzPSLnqpflj6MoVykiID4NCg0KICAgICAgICA8R3JvdXAgTmFtZT0iV2luZG93IiBBbGlhcz0i5Z+65pysIj4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkwMDEiIEJvdW5kcz0iMCwwLDIsMSIgTmFtZT0iVmlzaWJsZVByb2pUcmVlRGEiIEFsaWFzPSLpobnnm67moJEiIEljb249IlByb2pUcmVlIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTAwOCIgQm91bmRzPSIwLDEsMiwxIiBOYW1lPSJWaXNpYmxlUHJvalRyZWVKYiIgQWxpYXM9IuWIhuaekOagkSIgSWNvbj0iUHJvalRyZWUiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI5MDA5IiBCb3VuZHM9IjAsMiwyLDEiIE5hbWU9IlZpc2libGVQcm9qVHJlZVJzIiBBbGlhcz0i5oiQ5p6c5qCRIiBJY29uPSJQcm9qVHJlZSIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkwMDIiIEJvdW5kcz0iMCwzIiBOYW1lPSJWaXNpYmxlTW9kZWxzIiBBbGlhcz0i5qih5Z6L56qX5Y+jIiBJY29uPSJWaXNpYmxlTW9kZWxzIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTAwMyIgQm91bmRzPSIxLDMiIE5hbWU9IlZpc2libGVQYXJhbWV0ZXJzIiBBbGlhcz0i5Y+C5pWw56qX5Y+jIiBJY29uPSJWaXNpYmxlUGFyYW1ldGVycyIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkwMDQiIEJvdW5kcz0iMCw0IiBOYW1lPSJWaXNpYmxlUHR5cyIgQWxpYXM9IuWxnuaAp+eql+WPoyIgSWNvbj0iUHJvcGVydHlXaW5kb3ciIC8+DQogICAgICAgICAgICA8Q21kIElEPSI5MDA1IiBCb3VuZHM9IjEsNCIgTmFtZT0iVmlzaWJsZUxvZ3MiIEFsaWFzPSLml6Xlv5fnqpflj6MiIEljb249IlZpc2libGVMb2dzIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTAwNiIgQm91bmRzPSIwLDUiIE5hbWU9IlN0YWNrZWRQcm9qZWN0IiBBbGlhcz0i6aG555uu56qX5L2TIiBJY29uPSJTdGFja2VkUHJvamVjdCIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkwMDciIEJvdW5kcz0iMSw1IiBOYW1lPSJTdGFja2VkTWRpIiBBbGlhcz0i5YiG5p6Q56qX5L2TIiBJY29uPSJTdGFja2VkTWRpIiAvPg0KICAgICAgICA8L0dyb3VwPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJXaW5kb3dMYXlvdXQiIEFsaWFzPSLnqpflj6PluIPlsYAiPg0KICAgICAgICAgICAgPENtZCBJRD0iOTAxMSIgQm91bmRzPSIwLDAiIE5hbWU9IldpbmRvd0xheW91dEgiIEljb25Pbmx5PSIxIiBUaXBzPSLmsLTlubPluIPlsYAiIEljb249IldpbmRvd0xheW91dEgiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI5MDEyIiBCb3VuZHM9IjEsMCIgTmFtZT0iV2luZG93TGF5b3V0ViIgSWNvbk9ubHk9IjEiIFRpcHM9IuerluebtOW4g+WxgCIgSWNvbj0iV2luZG93TGF5b3V0ViIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkwMTMiIEJvdW5kcz0iMCwxIiBOYW1lPSJXaW5kb3dMYXlvdXRUIiBJY29uT25seT0iMSIgVGlwcz0i5bmz6ZO65biD5bGAIiBJY29uPSJXaW5kb3dMYXlvdXRUIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTAxNCIgQm91bmRzPSIxLDEiIE5hbWU9IldpbmRvd0xheW91dEMiIEljb25Pbmx5PSIxIiBUaXBzPSLmipjlj6DluIPlsYAiIEljb249IldpbmRvd0xheW91dEMiIC8+DQogICAgICAgIDwvR3JvdXA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9IkNsb3NlIiBBbGlhcz0i5YWz6ZetIj4gICAgICAgIA0KICAgICAgICAgICAgPENtZCBJRD0iOTAyMSIgQm91bmRzPSIwLDAiIE5hbWU9IkNsb3NlQ3VyV25kIiBBbGlhcz0i5YWz6Zet5b2T5YmNIiBJY29uPSJDbG9zZUFsbFdpbmRvdyIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkwMjIiIEJvdW5kcz0iMSwwIiBOYW1lPSJDbG9zZUFsbFduZHMiIEFsaWFzPSLlhbPpl63miYDmnIkiIEljb249IkNsb3NlQWxsV2luZG93IiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTAyMyIgQm91bmRzPSIwLDEiIE5hbWU9IlByZXZXbmQiIEFsaWFzPSLkuIrkuIDkuKoiIEljb25Pbmx5PSIxIiBJY29uPSJVcCIgVGlwcz0i5LiK5LiA5Liq56qX5L2TIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTAyNCIgQm91bmRzPSIxLDEiIE5hbWU9Ik5leHRXbmQiIEFsaWFzPSLkuIvkuIDkuKoiIEljb25Pbmx5PSIxIiBJY29uPSJEb3duIiBUaXBzPSLkuIvkuIDkuKrnqpfkvZMiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI5MDI1IiBCb3VuZHM9IjAsMiwyLDEiIFR5cGU9IjciIE5hbWU9Ikxpc3RXeFduZHMiIEFsaWFzPSLnqpfkvZMiIC8+DQogICAgICAgIDwvR3JvdXA+DQoNCiAgICA8L1RhYj4NCg0KICAgIDxUYWIgSUQ9IjEwIiBOYW1lPSJIZWxwIiBBbGlhcz0i5biu5YqpKEgpIiA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9IkhlbHAiIEFsaWFzPSLluK7liqkiPg0KICAgICAgICAgICAgPENtZCBJRD0iMTAwMDEiIEJvdW5kcz0iMCwwLDIsMSIgTmFtZT0iTG9nVmlldyIgQWxpYXM9IuaXpeW/l+afpeeciyhMKSIgSWNvbj0iTG9nVmlldyIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjEwMDAyIiBCb3VuZHM9IjAsMSwyLDEiIE5hbWU9IkhlbHAiIEFsaWFzPSLluK7liqkoSCkiIEljb249IkhlbHAiIC8+DQogICAgICAgICAgICA8Q21kIElEPSIxMDAwOCIgQm91bmRzPSIwLDIsMiwxIiBOYW1lPSJVcGRhdGVMaXN0cyIgQWxpYXM9IuabtOaWsOWIl+ihqChJKSIgSWNvbj0iVXBkYXRlTGlzdHMiIC8+DQogICAgICAgIDwvR3JvdXA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9IkxhbmciIEFsaWFzPSLor63oqIAiPg0KICAgICAgICAgICA8Q21kIElEPSIxMDAwOSIgQm91bmRzPSIwLDAsMiwxIiBOYW1lPSJMYW5nU3dhcCIgQWxpYXM9IuWIh+aNouivreiogCIgSWNvbj0iTGFuZ1N3YXAiIC8+DQogICAgICAgIDwvR3JvdXA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9IkFib3V0IiBBbGlhcz0i5YWz5LqOIj4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjEwMDAzIiBCb3VuZHM9IjAsMCwyLDEiIE5hbWU9IkFib3V0IiBBbGlhcz0i5YWz5LqOKEEpIiBJY29uPSJXVEFJQWJvdXQiIC8+DQogICAgICAgICAgICA8Q21kIElEPSIxMDAwNCIgQm91bmRzPSIxLDAiIE5hbWU9IkFib3V0UXQiIEFsaWFzPSLlhbPkuo5RdChRKSIgSWNvbj0iUXQiIFZpc2libGU9IjAiIC8+DQogICAgICAgIDwvR3JvdXA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9IkxvZ2luIiBBbGlhcz0i55m75b2VKERlYnVnKSI+DQogICAgICAgICAgICA8Q21kIElEPSIxMDAwNyIgQm91bmRzPSIwLDAiIE5hbWU9IlJlZ2lzdGVyIiBBbGlhcz0iKERlYnVnKei9r+S7tuazqOWGjChSKSIgSWNvbj0iUmVnaXN0ZXIiIC8+DQogICAgICAgICAgICA8Q21kIElEPSIxMDAwNSIgQm91bmRzPSIxLDAiIE5hbWU9IkxvZ2luIiBBbGlhcz0iKERlYnVnKeeUqOaIt+eZu+W9lShVKSIgSWNvbj0iTG9naW4iIC8+DQogICAgICAgIDwvR3JvdXA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9IkRlYnVnIiBBbGlhcz0i6LCD6K+VKERlYnVnKSI+DQogICAgICAgICAgICA8Q21kIElEPSIxMDAwNiIgQm91bmRzPSIwLDAsMiwxIiBOYW1lPSIoRGVidWcpIFN1bSBQYXJhbWV0ZXJzIiBBbGlhcz0iKERlYnVnKeaxh+aAu+aooeWei+WPguaVsCIgSWNvbj0iU3VtUGFyYSIgLz4NCiAgICAgICA8L0dyb3VwPg0KICAgIDwvVGFiPg0KDQo8L1JpYmJvbj4NCg==
\ No newline at end of file
diff --git a/Bin/Config/Common/MenuDefines_Ribbon_en.dat b/Bin/Config/Common/MenuDefines_Ribbon_en.dat
index 5cdd7c5..154151c 100644
--- a/Bin/Config/Common/MenuDefines_Ribbon_en.dat
+++ b/Bin/Config/Common/MenuDefines_Ribbon_en.dat
@@ -1 +1 @@
-77u/PD94bWwgcup_mpadmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4NCg0KPCEtLSDnvJbovpHkvbwzy/nlKggWE1MU3B5IHYyMDA2IFUgKGh0dHA6Ly93d3cuYWx0b3ZhLmNvbSkg55SxIGFueSAoYW55KSAtLT4NCjwhLS0qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqLS0+DQo8IS0tICAgIOacrOaWh+aho+eahOebrueahOaYr+W7uueri1dUQUnova/ku7bns7vnu5/nmoToj5zljZXlsYLmrKHlhbPns7so6ZKI5a+5UmliYm9u5qih5byPKSAgICAgICAgICAgICAgICAgICAgICAgLS0+DQo8IS0tICAgIEF1dGhvcihzKTogd2FuZ3pnICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC0tPg0KPCEtLSAgICBEYXRlOiAyMDI0MDcxOCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAtLT4NCjwhLS0qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqLS0+DQoNCjwhLS0qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqLS0+DQo8IS0tDQogICAgVGFiIOe6p+WIqw0KICAgICAgICBJRDogICAgICAgICAg5ZSv5LiA5qCH6K+GDQogICAgICAgIE5hbWXvvJogICAgICAg5ZCN56ew77yM6YCa5bi46Iux5paHDQogICAgICAgIEFsaWFz77yaICAgICAg5Yir5ZCN77yM6YCa5bi45Lit5paHDQogICAgICAgIEZpbGVNb2RlOiAgICDmmK/lkKbmlofku7ZNZW515qih5byP77yMMSBvciAwDQogICAgICAgIFZpc2libGXvvJogICAg5piv5ZCm5Y+v6KeB77yMMSBvciAwDQogICAgICAgIFRpcHPvvJogICAgICAg6L6F5Yqp6K+05piODQoNCiAgICAgICAgR3JvdXAg57qn5YirDQogICAgICAgICAgICBOYW1l77yaICAgICAgIOWQjeensO+8jOmAmuW4uOiLseaWhw0KICAgICAgICAgICAgQWxpYXPvvJogICAgICDliKvlkI3vvIzpgJrluLjkuK3mlocNCg0KICAgICAgICAgICAgQ21kIOe6p+WIqw0KICAgICAgICAgICAgICAgIElEOiAgICAgICAgICDllK/kuIDmoIfor4YNCiAgICAgICAgICAgICAgICBUeXBlOiAgICAgICAg5a+55bqU5o6n5Lu257G75Z6LOg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAw4oCU4oCU6buY6K6kQnV0dG9uDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIDHigJTigJTluKbkuIvmi4noj5zljZVCdXR0b24NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMuKAlOKAlENvbWJvQm94DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIDPigJTigJRDaGVja0JveA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICA04oCU4oCUUmFkaW9CdXR0b24NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgNeKAlOKAlFRleHQNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgNuKAlOKAlExhYmVsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIDfigJTigJRMaXN0V2lkZ2V0DQogICAgICAgICAgICAgICAgTmFtZe+8miAgICAgICDlkI3np7DvvIzpgJrluLjoi7HmlocNCiAgICAgICAgICAgICAgICBBbGlhc++8miAgICAgIOWIq+WQje+8jOmAmuW4uOS4reaWhw0KICAgICAgICAgICAgICAgIEljb27vvJogICAgICAg5Zu+5qCHDQogICAgICAgICAgICAgICAgU2hvcnRLZXnvvJogICDlv6vmjbfplK4NCiAgICAgICAgICAgICAgICBCb3VuZHM6ICAgICAg5L2N572u5L+h5oGv77yM5YWo5piv5pW05pWw77yM5ZyoR3JpZExheW91dOS4rQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoMCwwLDEsMikgKDAsMCkg5YiG5Yir5Li6eHl3aA0KICAgICAgICAgICAgICAgIEV4dEluZm86ICAgICDmianlsZXkv6Hmga/vvIzlpoLmk43kvZzlr7nosaHnmoTooajlkI0s5LiL5ouJ6YCJ6aG5562JDQogICAgICAgICAgICAgICAgRXh0TmFtZXM6ICAgIOaJqeWxleS/oeaBr+WvueW6lOeahE5hbWXvvIzlpoLkuIvmi4lidXR0b27lr7nlupTnmoROYW1lDQogICAgICAgICAgICAgICAgVGlwc++8miAgICAgICDovoXliqnor7TmmI4NCi0tPg0KPCEtLSoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiotLT4NCg0KPFJpYmJvbj4NCg0KICAgIDxUYWIgSUQ9IjEiIE5hbWU9IlByb2pNYW5hZ2VyIiBBbGlhcz0iUHJvaiBNYW5hZ2VyIiBGaWxlTW9kZT0iMSIgPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJQcm9qZWN0IiBBbGlhcz0iRmlsZSI+DQogICAgICAgICAgICA8Q21kIElEPSIxMDAwIiBOYW1lPSJBcHBIb21lIiBBbGlhcz0iIiBJY29uPSJBcHBIb21lMTI4IiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iLTEiIE5hbWU9IlNlcGFyYXRvciIgQWxpYXM9IlNlcGFyYXRvciIgVGlwcz0iIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMTAwMSIgTmFtZT0iUHJvak5ldyIgQWxpYXM9Ik5ldyBwcm9qZWN0IiBTaG9ydEtleT0iQ3RybCtOIiBJY29uPSJOZXdQcm9qIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMTAwMiIgTmFtZT0iUHJvak9wZW4iIEFsaWFzPSJPcGVuIHByb2plY3QiIFNob3J0S2V5PSJDdHJsK08iIEljb249Ik9wZW5Qcm9qIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMTAwMyIgTmFtZT0iUHJvakNsb3NlIiBBbGlhcz0iQ2xvc2UgcHJvamVjdCIgSWNvbj0iQ2xvc2VQcm9qIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iLTEiIE5hbWU9IlNlcGFyYXRvciIgQWxpYXM9IlNlcGFyYXRvciIgVGlwcz0iIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMTAwNSIgTmFtZT0iUHJvalNhdmUiIEFsaWFzPSJTYXZlIHByb2plY3QiIFNob3J0S2V5PSJDdHJsK1MiIEljb249IlNhdmVQcm9qIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMTAwNiIgTmFtZT0iUHJvalNhdmVBcyIgQWxpYXM9IlNhdmUgcHJvamVjdCBhcyIgSWNvbj0iU2F2ZWFzIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMTAwNyIgTmFtZT0iUHJvakNvbmZpZyIgQWxpYXM9IlByb2plY3RJbmZvIiBJY29uPSJQcm9qSW5mbyIgLz4NCg0KICAgICAgICAgICAgPENtZCBJRD0iLTEiIE5hbWU9IlNlcGFyYXRvciIgQWxpYXM9IlNlcGFyYXRvciIgVGlwcz0iIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMTAwMDIiIE5hbWU9IkhlbHAiIEFsaWFzPSJIZWxwIiBJY29uPSJIZWxwIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMTAwMDMiIE5hbWU9IkFib3V0IiBBbGlhcz0iQWJvdXQiIEljb249IldUQUlBYm91dCIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjEwMDA4IiBOYW1lPSJVcGRhdGVMaXN0cyIgQWxpYXM9IlVwZGF0ZSBsaXN0cyIgSWNvbj0iVXBkYXRlTGlzdHMiIC8+DQogICAgICAgICAgICA8Q21kIElEPSItMSIgTmFtZT0iU2VwYXJhdG9yIiBBbGlhcz0iU2VwYXJhdG9yIiBUaXBzPSIiIC8+DQogICAgICAgICAgICA8Q21kIElEPSIxMDEwIiBOYW1lPSJBcHBRdWl0IiBBbGlhcz0iUXVpdChYKSIgSWNvbj0iQ2xvc2UiIC8+DQogICAgICAgIDwvR3JvdXA+DQogICAgPC9UYWI+DQoNCiAgICA8VGFiIElEPSIwIiBOYW1lPSJXZWxDb21lIiBBbGlhcz0iU3RhcnQiID4NCg0KICAgICAgICA8R3JvdXAgTmFtZT0iRGF0YU1hbmFnZXIiIEFsaWFzPSJEYXRhIj4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjEwOTkiIEJvdW5kcz0iMCwwLDIsMSIgTmFtZT0iV2VsbE5ldyIgQWxpYXM9Ik5ldyB3ZWxsIiBJY29uPSJXZWxsTmV3IiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMjAwNSIgQm91bmRzPSIwLDEsMiwxIiBOYW1lPSJEYXRhUmF0ZSIgQWxpYXM9IlJhdGUiIEV4dEluZm89IlBfREFUQV9HQVVHRV9GIiBJY29uPSJSYXRlRGF0YSIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjIwMDYiIEJvdW5kcz0iMCwyLDIsMSIgTmFtZT0iRGF0YVByZSIgQWxpYXM9IlByZXNzdXJlIiBFeHRJbmZvPSJQX0RBVEFfR0FVR0VfUCIgSWNvbj0iUHJlc3N1cmVEYXRhIiAvPg0KICAgICAgICA8L0dyb3VwPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJBbmFsRWRpdCIgQWxpYXM9IkFuYWwiPg0KICAgICAgICAgICAgPENtZCBJRD0iMzAwNiIgQm91bmRzPSIwLDAsMiwxIiBOYW1lPSJBbmFsTmV3IiBBbGlhcz0iTmV3IGFuYWx5c2lzIiBJY29uPSJKb2JOZXciIC8+DQogICAgICAgICAgICA8Q21kIElEPSIzMDA3IiBCb3VuZHM9IjAsMSwyLDEiIE5hbWU9IkFuYWxFZGl0IiBBbGlhcz0iTWFuYWdpbmciIEljb249IkpvYkVkaXQiIFZpc2libGU9IjAiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI5MTAxIiBCb3VuZHM9IjAsMSIgTmFtZT0iVmlzaWJsZUFuYWxCYXNpYyIgQWxpYXM9IkJhc2ljIGluZm8iIEljb249IklucHV0QmFzaWMiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI5MTAyIiBCb3VuZHM9IjEsMSIgTmFtZT0iVmlzaWJsZUFuYWxQVlQiIEFsaWFzPSJQVlQgaW5mbyIgSWNvbj0iSW5wdXRGbHVpZCIgLz4NCiAgICAgICAgPC9Hcm91cD4NCg0KICAgICAgICA8R3JvdXAgTmFtZT0iQW5hbHl0aWNhbCIgQWxpYXM9IkZsb3cgcGVyaW9kIGFuYWwiPg0KICAgICAgICAgICAgPENtZCBJRD0iMzAwMyIgQm91bmRzPSIwLDAsMiwxIiBOYW1lPSJBbmFsUEYiIEFsaWFzPSJQZXJpb2Qgc2VsZWN0IiBFeHRJbmZvPSJQRiIgSWNvbj0iUEYiIC8+DQogICAgICAgICAgICA8Q21kIElEPSIzMDA0IiBCb3VuZHM9IjAsMSwyLDEiIE5hbWU9IkFuYWxGbG93U2VnIiBBbGlhcz0iUGVyaW9kIGFuYWwiIEljb249IkZsb3dQZXJpb2QiIC8+DQogICAgICAgIDwvR3JvdXA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9IkFuYWx5dGljYWwiIEFsaWFzPSJJbnRlcnByZXRhdGlvbiBGaXR0aW5nIj4NCg0KICAgICAgICAgICAgPENtZCBJRD0iMzEwNSIgQm91bmRzPSIwLDAsMiwxIiBOYW1lPSJEZWNvbnZvbHYiIEFsaWFzPSJEZWNvbnZvbHV0aW9uIiBJY29uPSJEZWNvbnZvbHYiIFZpc2libGU9IjAiIC8+DQogICAgICAgICAgICA8Q21kIElEPSIzMTAxIiBCb3VuZHM9IjAsMSwyLDEiIE5hbWU9IkZpdE1vZGVsIiBBbGlhcz0iQW5hbHl0aWNhbCIgSWNvbj0iRml0TW9kZWwiIC8+DQogICAgICAgICAgICA8Q21kIElEPSIzMTA0IiBCb3VuZHM9IjAsMiwyLDEiIE5hbWU9Im5tRml0TW9kZWwiIEFsaWFzPSJOdW1lcmljYWwiIEljb249IkZpdE1vZGVsIiAvPg0KDQogICAgICAgICAgICA8Q21kIElEPSIzMTAyIiBCb3VuZHM9IjAsMywyLDEiIE5hbWU9IkF1dG9GaXQiIEFsaWFzPSJGaXR0aW5nIiBJY29uPSJBdXRvRml0IiAvPg0KICAgICAgIDwvR3JvdXA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9Ik51bWVyaWNhbCIgQWxpYXM9Ikdlb2xvZ2ljYWwgTW9kZWxpbmcoRGVidWcpIiBWaXNpYmxlPSIwIj4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjUwMDIiIEJvdW5kcz0iMCwwLDIsMSIgTmFtZT0iUHJvcGVydHlMb2FkIiBBbGlhcz0iUHJvcGVydHkgSW1wb3J0IiBJY29uPSJQcmVwYXJlR3JpZCIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjUxMDIiIEJvdW5kcz0iMCwxLDIsMSIgTmFtZT0iUnVuR3JpZCIgQWxpYXM9IkdyaWQgR2VuZXJhdGlvbiIgSWNvbj0iUGxhdGVGaXQiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI1MjAxIiBCb3VuZHM9IjAsMiwyLDEiIE5hbWU9IkFuYWxNYXAiIEFsaWFzPSJDYWxjdWxhdGlvbiIgSWNvbj0iUnVuRXgiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI1MjAyIiBCb3VuZHM9IjAsMywyLDEiIE5hbWU9IkFuYWxQRiIgQWxpYXM9IkF1eGlsaWFyeSBGaXR0aW5nIiBFeHRJbmZvPSJQRiIgSWNvbj0iUnVuT3RoZXIiIFZpc2libGU9IjAiLz4NCiAgICAgICA8L0dyb3VwPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJXZWxsTWFwIiBBbGlhcz0iV2VsbCBNYXAiPg0KICAgICAgICAgICAgPENtZCBJRD0iMzAwOCIgQm91bmRzPSIwLDAsMiwxIiBOYW1lPSJBbmFsTWFwIiBBbGlhcz0iTWFwIiBJY29uPSJNYXAyRCIgVmlzaWJsZT0iMSIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjMwMTgiIEJvdW5kcz0iMCwxLDIsMSIgTmFtZT0iQW5hbEludGVyZmVyZSIgQWxpYXM9IkludGVyZmVyZW5jZSBTZXR0aW5nIiBJY29uPSJNYXAyRCIgVmlzaWJsZT0iMCIgLz4NCiAgICAgICAgPC9Hcm91cD4NCg0KICAgICAgICA8R3JvdXAgTmFtZT0iV2luZG93IiBBbGlhcz0iV2luZG93IERpc3BsYXkoRGVidWcpIiBWaXNpYmxlPSIwIiA+DQogICAgICAgICAgICA8Q21kIElEPSI5MDAyIiBCb3VuZHM9IjAsMCIgTmFtZT0iVmlzaWJsZU1vZGVscyIgQWxpYXM9Ik1vZGVsIFdpbmRvdyIgSWNvbj0iVmlzaWJsZU1vZGVscyIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkwMDMiIEJvdW5kcz0iMSwwIiBOYW1lPSJWaXNpYmxlUGFyYW1ldGVycyIgQWxpYXM9IlBhcmFtZXRlciBXaW5kb3ciIEljb249IlZpc2libGVQYXJhbWV0ZXJzIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTEwMSIgQm91bmRzPSIwLDEiIE5hbWU9IlZpc2libGVBbmFsQmFzaWMiIEFsaWFzPSJCYXNpYyBJbmZvIiBJY29uPSJJbnB1dEJhc2ljIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTEwMiIgQm91bmRzPSIxLDEiIE5hbWU9IlZpc2libGVBbmFsUFZUIiBBbGlhcz0iUFZUIERhdGEiIEljb249IklucHV0Rmx1aWQiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI5MTAzIiBCb3VuZHM9IjAsMiIgTmFtZT0iVmlzaWJsZUFuYWxEaWZmIiBBbGlhcz0iRElGRiBEYXRhIiBJY29uPSJJbnB1dEZsdWlkIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTEwNCIgQm91bmRzPSIxLDIiIE5hbWU9IlZpc2libGVBbmFsUHNldSIgQWxpYXM9IlBzZXVkbyBQcmVzc3VyZSBEYXRhIiBJY29uPSJJbnB1dEZsdWlkIiAvPg0KICAgICAgICA8L0dyb3VwPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJIZWxwIiBBbGlhcz0iSGVscCI+DQogICAgICAgICAgICA8Q21kIElEPSIxMDAwMiIgQm91bmRzPSIwLDAsMiwxIiBOYW1lPSJIZWxwIiBBbGlhcz0iSGVscCIgSWNvbj0iSGVscCIgLz4NCiAgICAgICAgPC9Hcm91cD4NCg0KICAgIDwvVGFiPg0KDQoNCiAgICA8VGFiIElEPSIyIiBOYW1lPSJEYXRhTWFuYWdlciIgQWxpYXM9IkRhdGEgTWFuYWdlciIgPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJEYXRhTWFuYWdlciIgQWxpYXM9IldlbGwiPg0KICAgICAgICAgICAgPENtZCBJRD0iMTA5OSIgQm91bmRzPSIwLDAsMiwxIiBOYW1lPSJXZWxsTmV3IiBBbGlhcz0iTmV3IFdlbGwoVykiIEljb249IldlbGxOZXciIC8+DQogICAgICAgIDwvR3JvdXA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9IkRhdGFNYW5hZ2VyIiBBbGlhcz0iQmFzaWMgRGF0YSI+DQogICAgICAgICAgICA8Q21kIElEPSIyMDAxIiBCb3VuZHM9IjAsMCwyLDEiIE5hbWU9IkRhdGFXZWxsQmFzaWMiIEFsaWFzPSJXZWxsIEJhc2ljIERhdGEoQikiIEV4dEluZm89IkJfV0VMTCIgSWNvbj0iQmFzaWNEYXRhIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMjAwMiIgQm91bmRzPSIwLDEsMiwxIiBOYW1lPSJEYXRhTGF5ZXIiIEFsaWFzPSJHZW9sb2dpY2FsIExheWVyIERhdGEoTCkiIEV4dEluZm89IkJfTEFZRVIiIEljb249IkxheWVyRGF0YSIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjIwMDMiIEJvdW5kcz0iMCwyLDIsMSIgTmFtZT0iRGF0YVJlcyIgQWxpYXM9IlJlc2Vydm9pciBEYXRhKFIpIiBFeHRJbmZvPSJQX0RBVEFfUkVTIiBJY29uPSJSZXNEYXRhIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMjAwNCIgQm91bmRzPSIwLDMsMiwxIiBOYW1lPSJEYXRhRmx1IiBBbGlhcz0iRmx1aWQgUHJvcGVydHkgRGF0YShGKSIgRXh0SW5mbz0iUF9EQVRBX0ZMVUlEIiBJY29uPSJGbHVpZFByb3BlcnR5IiAvPg0KICAgICAgICA8L0dyb3VwPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJEYXRhTWFuYWdlciIgQWxpYXM9IlByZXNzdXJlIFJhdGUiPg0KICAgICAgICAgICAgPENtZCBJRD0iMjAwNSIgQm91bmRzPSIwLDAsMiwxIiBOYW1lPSJEYXRhUmF0ZSIgQWxpYXM9IlJhdGUgRGF0YShRKSIgRXh0SW5mbz0iUF9EQVRBX0dBVUdFX0YiIEljb249IlJhdGVEYXRhIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMjAwNiIgQm91bmRzPSIwLDEsMiwxIiBOYW1lPSJEYXRhUHJlIiBBbGlhcz0iUHJlc3N1cmUgRGF0YShQKSIgRXh0SW5mbz0iUF9EQVRBX0dBVUdFX1AiIEljb249IlByZXNzdXJlRGF0YSIgLz4NCiAgICAgICAgPC9Hcm91cD4NCg0KICAgICAgICA8R3JvdXAgTmFtZT0iR1g2IiBBbGlhcz0iUGxhdGZvcm0gSW50ZXJvcGVyYWJpbGl0eSI+DQogICAgICAgICAgICA8Q21kIElEPSIyMDA3IiBCb3VuZHM9IjAsMCwyLDEiIE5hbWU9Ikd4NkNvbm5lY3RTZXJ2ZXIiIEFsaWFzPSJHWDYgSW50ZXJvcGVyYWJpbGl0eShDKSIgSWNvbj0iR3g2Q29ubmVjdFNlcnZlciIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjIwMDgiIEJvdW5kcz0iMCwxLDIsMSIgTmFtZT0iR3g2R2V0VGFza3MiIEFsaWFzPSJHZXQgVGFza3MoRCkiIEljb249Ikd4NkdldFRhc2tzIiAgVmlzaWJsZT0iMCIvPg0KICAgICAgICAgICAgPENtZCBJRD0iMjAwOSIgQm91bmRzPSIwLDIsMiwxIiBOYW1lPSJHeDZVcGRhdGVUYXNrcyIgQWxpYXM9IlVwZGF0ZSBTdGF0dXMoVSkiIEljb249Ikd4NlVwZGF0ZVRhc2tzIiAgVmlzaWJsZT0iMCIvPg0KICAgICAgICA8L0dyb3VwPg0KDQogICAgPC9UYWI+DQoNCiAgICA8VGFiIElEPSIyMDEiIE5hbWU9IkRhdGFFZGl0IiBBbGlhcz0iRGF0YSBFZGl0IiA+DQogICAgICAgIDxHcm91cCBOYW1lPSJEYXRhRWRpdCIgQWxpYXM9IkRhdGEgRWRpdGluZyI+DQogICAgICAgICAgICA8Q21kIElEPSIzMDAxIiBCb3VuZHM9IjAsMCwyLDEiIE5hbWU9IkFuYWxGbHUiIEFsaWFzPSJSYXRlIEVkaXRpbmciIEV4dEluZm89IkYiIE1kaVR5cGU9IkRhdGFFZGl0IiBJY29uPSJSYXRlRGF0YSIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjMwMDIiIEJvdW5kcz0iMCwxLDIsMSIgTmFtZT0iQW5hbFByZXNzIiBBbGlhcz0iUHJlc3N1cmUgRWRpdGluZyIgRXh0SW5mbz0iUCIgTWRpVHlwZT0iRGF0YUVkaXQiIEljb249IlByZXNzdXJlRGF0YSIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjMzMDMiIEJvdW5kcz0iMCwyLDIsMSIgTmFtZT0iQW5hbFByZUNvbiIgQWxpYXM9IlByZXNzdXJlIENvbnZlcnNpb24iIEV4dEluZm89IlAiIE1kaVR5cGU9IkRhdGFFZGl0IiBJY29uPSJBbmFsUHJlQ29uIiAvPg0KICAgICAgICA8L0dyb3VwPg0KICAgIDwvVGFiPg0KDQogICAgPFRhYiBJRD0iMyIgTmFtZT0iQW5hbHl0aWNhbFRlc3QiIEFsaWFzPSJJbnRlcnByZXRhdGlvbiIgPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJBbmFsRWRpdCIgQWxpYXM9IkFuYWx5c2lzIE1hbmFnZW1lbnQiPg0KICAgICAgICAgICAgPENtZCBJRD0iMzAwNiIgQm91bmRzPSIwLDAiIE5hbWU9IkFuYWxOZXciIEFsaWFzPSJOZXcgQW5hbHlzaXMiIEljb249IkpvYk5ldyIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjMwMDciIEJvdW5kcz0iMSwwIiBOYW1lPSJBbmFsRWRpdCIgQWxpYXM9IkFuYWx5c2lzIE1hbmFnZW1lbnQiIEljb249IkpvYkVkaXQiIC8+DQogICAgICAgIDwvR3JvdXA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9IlNlZ0FuYWwiIEFsaWFzPSJGbG93IFBlcmlvZCBBbmFseXNpcyI+DQogICAgICAgICAgICA8Q21kIElEPSIzMDAzIiBCb3VuZHM9IjAsMCwyLDEiIE5hbWU9IkFuYWxQRiIgQWxpYXM9IkZsb3cgUGVyaW9kIFNlbGVjdGlvbiIgRXh0SW5mbz0iUEYiIEljb249IlBGIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMzAwNCIgQm91bmRzPSIwLDEsMiwxIiBOYW1lPSJBbmFsRmxvd1NlZyIgQWxpYXM9IkZsb3cgUGVyaW9kIEFuYWx5c2lzIiBJY29uPSJGbG93UGVyaW9kIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMzAwNSIgQm91bmRzPSIwLDIsMiwxIiBOYW1lPSJBbmFsT3RoZXJzIiBBbGlhcz0iQ2hhcmFjdGVyaXN0aWMgTGluZSBBbmFseXNpcyIgVHlwZT0iMSIgIFZpc2libGU9IjAiIEV4dE5hbWVzPSJDaGFydFQ7Q2hhcnRTcXJ0VDtDaGFydDI1VDtDaGFydDVUIiBFeHRJbmZvPSJDaGFydCBUO0NoYXJ0IFNxcnQoVCk7Q2hhcnQgMC4yNVQ7Q2hhcnQgLTAuNVQiIEljb249IkFzc2lzQW5hbCIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjMwMTAiIEJvdW5kcz0iMCwzLDIsMSIgTmFtZT0iQW5hbFduZE0iIEFsaWFzPSJGbG93IFBlcmlvZCBXaW5kb3ciIFR5cGU9IjEiIEljb249IkFuYWxXbmRNIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMzAwOSIgQm91bmRzPSIwLDQsMiwxIiBOYW1lPSJBbmFsRGlzdHJpIiBBbGlhcz0iRGlzdHJpYnV0aW9uIENoYXJ0IiBUeXBlPSIxIiBFeHROYW1lcz0iQ2hhcnREZW47Q2hhcnRWaXMiIEV4dEluZm89IkNvbmNlbnRyYXRpb24gRGlzdHJpYnV0aW9uO1Zpc2Nvc2l0eSBEaXN0cmlidXRpb24iIEljb249IkFuYWxEaXN0cmkiIC8+DQogICAgICAgIDwvR3JvdXA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9IkRhdGFGaXQiIEFsaWFzPSJJbnRlcnByZXRhdGlvbiBGaXR0aW5nIj4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjMxMDUiIEJvdW5kcz0iMCwwLDIsMSIgTmFtZT0iRGVjb252b2x2IiBBbGlhcz0iRGVjb252b2x1dGlvbihEZWJ1ZykiIEljb249IkRlY29udm9sdiIgLz4NCg0KICAgICAgICAgICAgPENtZCBJRD0iMzEwMSIgQm91bmRzPSIwLDEsMiwxIiBOYW1lPSJGaXRNb2RlbCIgQWxpYXM9IkFuYWx5dGljYWwgU29sdXRpb24iIEljb249IkZpdE1vZGVsIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMzEwNCIgQm91bmRzPSIwLDIsMiwxIiBOYW1lPSJubUZpdE1vZGVsIiBBbGlhcz0iTnVtZXJpY2FsIFNvbHV0aW9uIiBJY29uPSJGaXRNb2RlbCIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjMxMDIiIEJvdW5kcz0iMCwzLDIsMSIgTmFtZT0iQXV0b0ZpdCIgQWxpYXM9IkF1dG8gRml0dGluZyIgSWNvbj0iQXV0b0ZpdCIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjMxMDMiIEJvdW5kcz0iMCw0LDIsMSIgTmFtZT0iUGxhdGVGaXQiIEFsaWFzPSJTZW5zaXRpdml0eSBBbmFseXNpcyIgSWNvbj0iUGxhdGVGaXQiIC8+DQogICAgICAgPC9Hcm91cD4NCg0KICAgICAgICA8R3JvdXAgTmFtZT0iQUlUZXN0IiBBbGlhcz0iSW50ZWxsaWdlbnQgV2VsbCBUZXN0aW5nIj4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjM5MDEiIEJvdW5kcz0iMCwwLDIsMSIgTmFtZT0iTW9kZWxDbGFzc2lmeSIgQWxpYXM9Ik1vZGVsIFJlY29nbml0aW9uIiBJY29uPSJNb2RlbENsYXNzaWZ5IiAvPg0KICAgICAgICA8L0dyb3VwPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJSZWxhdGl2ZVRvb2wiIEFsaWFzPSJSZWxhdGVkIFRvb2xzIj4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjMyMDEiIEJvdW5kcz0iMCwwLDIsMSIgTmFtZT0iVGltZSIgQWxpYXM9IlRpbWUiIEljb249IlRpbWUiIC8+DQogICAgICAgICAgICA8Q21kIElEPSIzMjAyIiBCb3VuZHM9IjAsMSIgTmFtZT0iU2hvd01vZGVsQ2hhcnRzIiBBbGlhcz0iTW9kZWwgU2NoZW1hdGljIiBJY29uPSJTaG93TW9kZWxDaGFydHMiIC8+DQogICAgICAgICAgICA8Q21kIElEPSIzMjA0IiBCb3VuZHM9IjEsMSIgTmFtZT0iU2F2ZUFzTW9kZWxTa2V0Y2giIEFsaWFzPSJTYXZlIEFzIFNjaGVtYXRpYyIgSWNvbj0iU2F2ZUFzTW9kZWxTa2V0Y2giIC8+DQoNCiAgICAgICA8L0dyb3VwPg0KDQo8IS0tICAgICAgICAgICAgICAgICAgICA8Q21kIElEPSIzMjAzIiBCb3VuZHM9IjAsMSIgTmFtZT0iU2hvd01vZGVsU2tldGNoIiBBbGlhcz0iVGhlb3J5IiBJY29uPSJTaG93TW9kZWxTa2V0Y2giIC8+PEdyb3VwIE5hbWU9IlRvb2xTIiBBbGlhcz0iRXh0ZW5kZWQgRnVuY3Rpb25zIj4NCiAgICAgICAgICAgIDxDbWQgSUQ9Ijk4MDEiIEJvdW5kcz0iMCwwLDIsMSIgTmFtZT0iRmxvd1RvUyIgQWxpYXM9IlJhdGUgdG8gU2tpbiBGYWN0b3IiIEljb249IkZsb3dUb1MiIFZpc2libGU9IjAiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI5MjAxIiBCb3VuZHM9IjAsMSwyLDEiIE5hbWU9Ik1peFZpc2Nvc2l0eSIgQWxpYXM9Ik1peGVkIFZpc2Nvc2l0eSIgSWNvbj0iTWl4VmlzY29zaXR5IiBWaXNpYmxlPSIwIiAvPg0KICAgICAgIDwvR3JvdXA+LS0+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9IkpvYnMiIEFsaWFzPSJSZXN1bHQgTWFuYWdlbWVudCI+DQogICAgICAgICAgICA8Q21kIElEPSIxMDA4IiBCb3VuZHM9IjAsMCIgTmFtZT0iUnN0TG9hZCIgQWxpYXM9IkxvYWQgUmVzdWx0cyIgSWNvbj0iTG9hZEpvYnMiIC8+DQogICAgICAgICAgICA8Q21kIElEPSIxMDA5IiBCb3VuZHM9IjEsMCIgTmFtZT0iUnN0U2F2ZSIgVHlwZT0iMSIgRXh0TmFtZXM9IlJzdFNhdmVDdXI7UnN0U2F2ZUFsbCIgRXh0SW5mbz0iU2F2ZSBDdXJyZW50IFJlc3VsdDtTYXZlIEFsbCBSZXN1bHRzIiBBbGlhcz0iU2F2ZSBSZXN1bHRzIiBJY29uPSJTYXZlSm9icyIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjEwMTEiIEJvdW5kcz0iMCwxLDIsMSIgTmFtZT0iVG9OdW1lcmljYWwiIEFsaWFzPSJUby1OdW1lcmljYWwiIEljb249IkxvYWRKb2JzIiBWaXNpYmxlPSIwIiAvPg0KICAgICAgICA8L0dyb3VwPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJXaW5kb3ciIEFsaWFzPSJXaW5kb3cgRGlzcGxheSI+DQogICAgICAgICAgICA8Q21kIElEPSI5MDAyIiBCb3VuZHM9IjAsMCIgTmFtZT0iVmlzaWJsZU1vZGVscyIgQWxpYXM9Ik1vZGVsIFdpbmRvdyIgSWNvbj0iVmlzaWJsZU1vZGVscyIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkwMDMiIEJvdW5kcz0iMSwwIiBOYW1lPSJWaXNpYmxlUGFyYW1ldGVycyIgQWxpYXM9IlBhcmFtZXRlciBXaW5kb3ciIEljb249IlZpc2libGVQYXJhbWV0ZXJzIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTEwMSIgQm91bmRzPSIwLDEiIE5hbWU9IlZpc2libGVBbmFsQmFzaWMiIEFsaWFzPSJCYXNpYyBJbmZvIiBJY29uPSJJbnB1dEJhc2ljIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTEwMiIgQm91bmRzPSIxLDEiIE5hbWU9IlZpc2libGVBbmFsUFZUIiBBbGlhcz0iUFZUIERhdGEiIEljb249IklucHV0Rmx1aWQiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI5MTAzIiBCb3VuZHM9IjAsMiIgTmFtZT0iVmlzaWJsZUFuYWxEaWZmIiBBbGlhcz0iRElGRiBEYXRhIiBJY29uPSJJbnB1dEZsdWlkIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTEwNCIgQm91bmRzPSIxLDIiIE5hbWU9IlZpc2libGVBbmFsUHNldSIgQWxpYXM9IlBzZXVkbyBQcmVzc3VyZSBEYXRhIiBJY29uPSJJbnB1dEZsdWlkIiAvPg0KICAgICAgICA8L0dyb3VwPg0KICAgIDwvVGFiPg0KDQogICAgPFRhYiBJRD0iNSIgTmFtZT0iTnVtZXJpY2FsVGVzdCIgQWxpYXM9Ik1vZGVsaW5nIiA+DQogICAgICAgIDxHcm91cCBOYW1lPSJObU1hbmFnZXIiIEFsaWFzPSJBbmFseXNpcyBNYW5hZ2VtZW50IiBWaXNpYmxlPSIwIj4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjUwMDEiIEJvdW5kcz0iMCwwLDIsMSIgTmFtZT0iQW5hbE5ldyIgQWxpYXM9IlRlbXBvcmFyeSBUZXN0IDEiIEljb249IlByZXBhcmVHcmlkIiBWaXNpYmxlPSIwIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iNTAwMiIgQm91bmRzPSIwLDEsMiwxIiBOYW1lPSJQcm9wZXJ0eUxvYWQiIEFsaWFzPSJUZW1wb3JhcnkgVGVzdCAyIiBJY29uPSJQcmVwYXJlR3JpZCIgIFZpc2libGU9IjAiLz4NCiAgICAgICAgPC9Hcm91cD4NCg0KICAgICAgICA8R3JvdXAgTmFtZT0iTm1BbmFsQ2hhbmdlIiBBbGlhcz0iQW5hbHlzaXMgU3dpdGNoIj4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjUxMzAiIEJvdW5kcz0iMCwwIiBOYW1lPSJObUFuYWxDaGFuZ2UiIEFsaWFzPSJBbmFseXNpcyBTd2l0Y2giIEljb249IkpvYkVkaXQiIC8+DQogICAgICAgPC9Hcm91cD4NCg0KICAgICAgICA8R3JvdXAgTmFtZT0iTnRJbml0IiBBbGlhcz0iTW9kZWwgR2VvbWV0cmljIE9iamVjdHMiPg0KICAgICAgICAgICAgPENtZCBJRD0iNTExOCIgQm91bmRzPSIwLDAsMiwxIiBOYW1lPSJObU1hcCIgQWxpYXM9Ik1hcCIgSWNvbj0iTm1JbWFnZSIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjUxMTkiIEJvdW5kcz0iMCwxLDIsMSIgTmFtZT0iTm1VbmxvY2tlZCIgQWxpYXM9IkxvY2siIEljb249Ik5tVW5sb2NrZWQiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI1MTAyIiBCb3VuZHM9IjAsMiwyLDEiIE5hbWU9Ik5tSW1hZ2UiIEFsaWFzPSJSZXNlcnZvaXIgTWFwIiBJY29uPSJObUltYWdlIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iNTEyMCIgQm91bmRzPSIwLDMsMiwxIiBOYW1lPSJObU1lYXN1cmUiIEFsaWFzPSJTY2FsZSBCYXIiIEljb249Ik5tTWVhc3VyZSIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjUxMDMiIEJvdW5kcz0iMCw0LDIsMSIgTmFtZT0iTm1Qb2x5Z29uIiBBbGlhcz0iUG9seWdvbiBCb3VuZGFyeSIgSWNvbj0iTm1Qb2x5Z29uIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iNTEwNCIgQm91bmRzPSIwLDUiIE5hbWU9Ik5tUG9seWdvbiIgQWxpYXM9IlJlY3RhbmdsZSBCb3VuZGFyeSIgSWNvbj0iTm1SZWN0YW5nbGUiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI1MTA1IiBCb3VuZHM9IjEsNSIgTmFtZT0iTm1Qb2x5Z29uIiBBbGlhcz0iQ2lyY2xlIEJvdW5kYXJ5IiBJY29uPSJObVJvdW5kIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iNTEwNiIgQm91bmRzPSIwLDYsMiwxIiBOYW1lPSJObUZhdWx0IiBBbGlhcz0iRmF1bHQiIEljb249Ik5tRmF1bHQiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI1MTA3IiBCb3VuZHM9IjAsNyIgTmFtZT0iTm1XZWxsIiBBbGlhcz0iU2VsZWN0IFdlbGwiIEljb249Ik5tV2VsbCIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjUxMDgiIEJvdW5kcz0iMSw3IiBOYW1lPSJObVdlbGwiIEFsaWFzPSJOZXcgV2VsbCIgSWNvbj0iTm1XZWxsIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iNTEwOSIgQm91bmRzPSIwLDgsMiwxIiBOYW1lPSJObUZhdWx0IiBBbGlhcz0iRnJhY3R1cmUiIEljb249Ik5tRmF1bHQiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI1MTEwIiBCb3VuZHM9IjAsOSIgTmFtZT0iTm1MaW1pdCIgQWxpYXM9IlJlZ2lvbiIgSWNvbj0iTm1MaW1pdCIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjUxMTEiIEJvdW5kcz0iMSw5IiBOYW1lPSJObVJlZ2lvbiIgQWxpYXM9Ik1hcmsgUmVnaW9uIiBJY29uPSJObVJlZ2lvbiIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjUxMjEiIEJvdW5kcz0iMCwxMCwyLDEiIE5hbWU9Ik5tRGVsZXRlIiBBbGlhcz0iRGVsZXRlIiBJY29uPSJObURlbGV0ZSIgLz4NCiAgICAgICA8L0dyb3VwPg0KDQogICAgICAgPEdyb3VwIE5hbWU9Ik50UmVzZXJ2b2lyIiBBbGlhcz0iUmVzZXJ2b2lyIENoYXJhY3RlcmlzdGljcyI+DQogICAgICAgICAgICA8Q21kIElEPSI1MTEyIiBCb3VuZHM9IjAsMCwyLDEiIE5hbWU9Ik5tR2VvbWV0cnkiIEFsaWFzPSJMYXllciBEaXZpc2lvbiIgSWNvbj0iTm1HZW9tZXRyeSIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjUxMTMiIEJvdW5kcz0iMCwxLDIsMSIgTmFtZT0iTm1Qcm9wZXJ0aWVzIiBBbGlhcz0iUmVzZXJ2b2lyIFByb3BlcnRpZXMiIEljb249Ik5tUHJvcGVydGllcyIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjUxMjIiIEJvdW5kcz0iMCwyLDIsMSIgTmFtZT0iTm1ERk4iIEFsaWFzPSJERk4iIEljb249Ik5tREZOIiAvPg0KICAgICAgIDwvR3JvdXA+DQoNCiAgICAgICA8R3JvdXAgTmFtZT0iTnRNb2RlbCIgQWxpYXM9Ik1vZGVsIEdlbmVyYXRpb24iPg0KICAgICAgICAgICAgIDxDbWQgSUQ9IjUxMTQiIEJvdW5kcz0iMCwwLDIsMSIgTmFtZT0iTm1HcmlkIiBBbGlhcz0iR3JpZCBHZW5lcmF0aW9uIiBJY29uPSJObUdyaWQiIC8+DQogICAgICAgICAgICAgPENtZCBJRD0iNTExNSIgQm91bmRzPSIwLDEsMiwxIiBOYW1lPSJObUNhY3VsYXRpb24iIEFsaWFzPSJDYWxjdWxhdGlvbiBTb2x1dGlvbiIgSWNvbj0iVGltZSIgLz4NCiAgICAgICAgICAgICA8IS0tDQogICAgICAgICAgICAgPENtZCBJRD0iNTExNiIgQm91bmRzPSIwLDIsMiwxIiBOYW1lPSJObUJhY2siIEFsaWFzPSJQb3N0IFByb2Nlc3NpbmciIEljb249IlRpbWUiIC8+DQogICAgICAgICAgICAgPENtZCBJRD0iNTExNyIgQm91bmRzPSIwLDMsMiwxIiBOYW1lPSJObVJlc3VsdCIgQWxpYXM9IlJlc3VsdCIgSWNvbj0iRmxvd1BlcmlvZCIgLz4NCiAgICAgICAgICAgICAtLT4NCiAgICAgICA8L0dyb3VwPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJOdFRvb2xzIiBBbGlhcz0iVG9vbHMiPg0KICAgICAgICAgICAgPENtZCBJRD0iNTEyNyIgQm91bmRzPSIwLDAiIE5hbWU9Ik5tR2VvUmVmZXJlbmNlIiBBbGlhcz0iTW9kZWwgUmVmZXJlbmNlIFBvaW50IFNldHRpbmciIEljb249Ik5tR2VvUmVmZXJlbmNlIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iNTEyOCIgQm91bmRzPSIxLDAiIE5hbWU9Ik5tUG9pbnRlclBvc2l0aW9uIiBBbGlhcz0iTW9kZWwgUG9zaXRpb24gRGlzcGxheSIgSWNvbj0iTm1Qb2ludGVyUG9zaXRpb24iIC8+DQogICAgICAgICAgICA8Q21kIElEPSI1MTI5IiBCb3VuZHM9IjAsMSwyLDEiIE5hbWU9Ik5tTWVhc3VyZSIgQWxpYXM9Ik1vZGVsIERpbWVuc2lvbiBNZWFzdXJlbWVudCIgSWNvbj0iTm1NZWFzdXJlIiAvPg0KICAgICAgIDwvR3JvdXA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9Ik50RGlzcGxheSIgQWxpYXM9IkRpc3BsYXkiPg0KICAgICAgICAgICAgPENtZCBJRD0iNTEyMyIgQm91bmRzPSIwLDAsMiwxIiBOYW1lPSJObVNob3ciIEFsaWFzPSJEaXNwbGF5IiBJY29uPSJObVNob3ciIC8+DQogICAgICAgICAgICA8Q21kIElEPSI1MTI0IiBCb3VuZHM9IjAsMSwyLDEiIE5hbWU9Ik5tUHJpbnRQcmV2aWV3IiBBbGlhcz0iUHJpbnQgUHJldmlldyIgSWNvbj0iTm1QcmludFByZXZpZXciIC8+DQogICAgICAgICAgICA8Q21kIElEPSI1MTI1IiBCb3VuZHM9IjAsMiwyLDEiIE5hbWU9Ik5tUHJpbnQiIEFsaWFzPSJQcmludCIgSWNvbj0iTm1QcmludCIgLz4NCiAgICAgICA8L0dyb3VwPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJXaW5kb3ciIEFsaWFzPSJXaW5kb3cgRGlzcGxheSIgIFZpc2libGU9IjAiPg0KICAgICAgICAgICAgPENtZCBJRD0iOTAwMiIgQm91bmRzPSIwLDAiIE5hbWU9IlZpc2libGVNb2RlbHMiIEFsaWFzPSJNb2RlbCBXaW5kb3ciIEljb249IlZpc2libGVNb2RlbHMiICBWaXNpYmxlPSIwIi8+DQogICAgICAgICAgICA8Q21kIElEPSI5MDAzIiBCb3VuZHM9IjEsMCIgTmFtZT0iVmlzaWJsZVBhcmFtZXRlcnMiIEFsaWFzPSJQYXJhbWV0ZXIgV2luZG93IiBJY29uPSJWaXNpYmxlUGFyYW1ldGVycyIgIFZpc2libGU9IjAiLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkxMDEiIEJvdW5kcz0iMCwxIiBOYW1lPSJWaXNpYmxlQW5hbEJhc2ljIiBBbGlhcz0iQmFzaWMgSW5mbyIgSWNvbj0iSW5wdXRCYXNpYyIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkxMDIiIEJvdW5kcz0iMSwxIiBOYW1lPSJWaXNpYmxlQW5hbFBWVCIgQWxpYXM9IlBWVCBEYXRhIiBJY29uPSJJbnB1dEZsdWlkIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTEwMyIgQm91bmRzPSIwLDIiIE5hbWU9IlZpc2libGVBbmFsRGlmZiIgQWxpYXM9IkRJRkYgRGF0YSIgSWNvbj0iSW5wdXRGbHVpZCIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkxMDQiIEJvdW5kcz0iMSwyIiBOYW1lPSJWaXNpYmxlQW5hbFBzZXUiIEFsaWFzPSJQc2V1ZG8gUHJlc3N1cmUgRGF0YSIgSWNvbj0iSW5wdXRGbHVpZCIgLz4NCiAgICAgICAgPC9Hcm91cD4NCg0KICAgICAgICA8R3JvdXAgTmFtZT0iTm1EZWJ1ZyIgQWxpYXM9IkZyYW1ld29yayBUZXN0KERlYnVnKSI+DQogICAgICAgICAgICA8Q21kIElEPSI1OTk5IiBCb3VuZHM9IjAsMCwyLDEiIE5hbWU9Ik5tRGVidWciIEFsaWFzPSJGcmFtZXdvcmsgQ29kZSBEZWJ1Z2dpbmciIEljb249IlByZXBhcmVHcmlkIiAvPg0KICAgICAgICA8L0dyb3VwPg0KDQoNCiAgICA8L1RhYj4NCg0KICAgIDxUYWIgSUQ9IjQiIE5hbWU9Ik1pbmlGcmFjIiBBbGlhcz0iTWluaSBGcmFjdHVyaW5nKERlYnVnKSIgPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJBbmFsRWRpdCIgQWxpYXM9IkFuYWx5c2lzIE1hbmFnZW1lbnQiPg0KICAgICAgICAgICAgPENtZCBJRD0iMzAwNiIgQm91bmRzPSIwLDAiIE5hbWU9IkFuYWxOZXciIEFsaWFzPSJOZXcgQW5hbHlzaXMiIEljb249IkpvYk5ldyIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjMwMDciIEJvdW5kcz0iMSwwIiBOYW1lPSJBbmFsRWRpdCIgQWxpYXM9IkFuYWx5c2lzIE1hbmFnZW1lbnQiIEljb249IkpvYkVkaXQiIC8+DQogICAgICAgIDwvR3JvdXA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9IlBBIiBBbGlhcz0iUHJlc3N1cmUgRHJvcCBBbmFseXNpcyI+DQogICAgICAgICAgICA8Q21kIElEPSI0MDAyIiBCb3VuZHM9IjAsMCwzLDEiIE5hbWU9Ik1pbmlGckFuYWxQQSIgQWxpYXM9IlByZXNzdXJlIERyb3AgUHJlcGFyYXRpb24iIEV4dEluZm89IlBGIiBJY29uPSJQRiIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjQwMDMiIEJvdW5kcz0iMCwxLDMsMSIgTmFtZT0iTWluaUZyUEEiIEFsaWFzPSJQcmVzc3VyZSBEcm9wIEFuYWx5c2lzIiBJY29uPSJGbG93UGVyaW9kIiAvPg0KDQogICAgICAgICAgICA8Q21kIElEPSI0MDA0IiBCb3VuZHM9IjAsMiwzLDEiIE5hbWU9IkNhbFN1ZGRlblN0b3BQIiBBbGlhcz0iSW5zdGFudGFuZW91cyBTaHV0LWluIFByZXNzdXJlIiBJY29uPSJSdW5FeCIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjQwMDUiIEJvdW5kcz0iMCwzIiBOYW1lPSJDYWxHRnVuY3Rpb24iIEFsaWFzPSJHIEZ1bmN0aW9uIiBJY29uPSJSdW5PdGhlciIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjQwMDYiIEJvdW5kcz0iMSwzIiBOYW1lPSJDYWxTcXJ0VCIgQWxpYXM9IlNxdWFyZSBSb290IG9mIFRpbWUiIEljb249IlJ1bk90aGVyIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iNDAwNyIgQm91bmRzPSIyLDMiIE5hbWU9IkNhbExvZ0xvZyIgQWxpYXM9IkxvZy1Mb2cgUGxvdCIgSWNvbj0iUnVuT3RoZXIiIC8+DQogICAgICAgIDwvR3JvdXA+DQoNCg0KICAgICAgICA8R3JvdXAgTmFtZT0iRkEiIEFsaWFzPSJGbG93IFJhdGUgQW5hbHlzaXMiPg0KICAgICAgICAgICAgPENtZCBJRD0iNDEwMiIgQm91bmRzPSIwLDAsMiwxIiBOYW1lPSJNaW5pRnJBbmFsRkEiIEFsaWFzPSJGbG93IFJhdGUgUHJlcGFyYXRpb24iIEV4dEluZm89IklQUiIgSWNvbj0iTWluaUZyQW5hbEZBIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iNDEwMyIgQm91bmRzPSIwLDEiIE5hbWU9Ik1pbmlGckZBVXAiIEFsaWFzPSJTdGVwIFVwIiBJY29uPSJTdGVwVXAiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI0MTA0IiBCb3VuZHM9IjEsMSIgTmFtZT0iTWluaUZyRkFEb3duIiBBbGlhcz0iU3RlcCBEb3duIiBJY29uPSJTdGVwRG93biIgLz4NCiAgICAgICA8L0dyb3VwPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJKb2JzIiBBbGlhcz0iUmVzdWx0IE1hbmFnZW1lbnQiICBWaXNpYmxlPSIwIj4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjEwMDgiIEJvdW5kcz0iMCwwIiBOYW1lPSJSc3RMb2FkIiBBbGlhcz0iTG9hZCBSZXN1bHRzIiBJY29uPSJMb2FkSm9icyIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjEwMDkiIEJvdW5kcz0iMSwwIiBOYW1lPSJSc3RTYXZlIiBUeXBlPSIxIiBFeHROYW1lcz0iUnN0U2F2ZUN1cjtSc3RTYXZlQWxsIiBFeHRJbmZvPSJTYXZlIEN1cnJlbnQgUmVzdWx0O1NhdmUgQWxsIFJlc3VsdHMiIEFsaWFzPSJTYXZlIFJlc3VsdHMiIEljb249IlNhdmVKb2JzIiAvPg0KICAgICAgICA8L0dyb3VwPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJXaW5kb3ciIEFsaWFzPSJXaW5kb3cgRGlzcGxheSIgIFZpc2libGU9IjAiPg0KICAgICAgICAgICAgPENtZCBJRD0iOTAwMiIgQm91bmRzPSIwLDAiIE5hbWU9IlZpc2libGVNb2RlbHMiIEFsaWFzPSJNb2RlbCBXaW5kb3ciIEljb249IlZpc2libGVNb2RlbHMiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI5MDAzIiBCb3VuZHM9IjEsMCIgTmFtZT0iVmlzaWJsZVBhcmFtZXRlcnMiIEFsaWFzPSJQYXJhbWV0ZXIgV2luZG93IiBJY29uPSJWaXNpYmxlUGFyYW1ldGVycyIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkxMDEiIEJvdW5kcz0iMCwxIiBOYW1lPSJWaXNpYmxlQW5hbEJhc2ljIiBBbGlhcz0iQmFzaWMgSW5mbyIgSWNvbj0iSW5wdXRCYXNpYyIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkxMDIiIEJvdW5kcz0iMSwxIiBOYW1lPSJWaXNpYmxlQW5hbFBWVCIgQWxpYXM9IlBWVCBEYXRhIiBJY29uPSJJbnB1dEZsdWlkIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTEwMyIgQm91bmRzPSIwLDIiIE5hbWU9IlZpc2libGVBbmFsRGlmZiIgQWxpYXM9IkRJRkYgRGF0YSIgSWNvbj0iSW5wdXRGbHVpZCIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkxMDQiIEJvdW5kcz0iMSwyIiBOYW1lPSJWaXNpYmxlQW5hbFBzZXUiIEFsaWFzPSJQc2V1ZG8gUHJlc3N1cmUgRGF0YSIgSWNvbj0iSW5wdXRGbHVpZCIgLz4NCiAgICAgICAgPC9Hcm91cD4NCg0KICAgIDwvVGFiPg0KDQogICAgPFRhYiBJRD0iNDAxIiBOYW1lPSJJUFIiIEFsaWFzPSJXZWxsIFByb2QgVGVzdCIgPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJBbmFsRWRpdCIgQWxpYXM9IkFuYWx5c2lzIE1hbmFnZW1lbnQiPg0KICAgICAgICAgICAgPENtZCBJRD0iMzAwNiIgQm91bmRzPSIwLDAiIE5hbWU9IkFuYWxOZXciIEFsaWFzPSJOZXcgQW5hbHlzaXMiIEljb249IkpvYk5ldyIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjMwMDciIEJvdW5kcz0iMSwwIiBOYW1lPSJBbmFsRWRpdCIgQWxpYXM9IkFuYWx5c2lzIE1hbmFnZW1lbnQiIEljb249IkpvYkVkaXQiIC8+DQogICAgICAgIDwvR3JvdXA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9IklQUiIgQWxpYXM9IklQUiBQcmV2aW91cyBSZWZlcmVuY2UoRGVidWcpIj4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjYwMDIiIEJvdW5kcz0iMCwwLDIsMSIgTmFtZT0iSVBSQW5hbCIgQWxpYXM9IklQUiBQcmVwYXJhdGlvbiIgRXh0SW5mbz0iSVBSIiBJY29uPSJJUFJBbmFsIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iNjAwMyIgQm91bmRzPSIwLDEsMiwxIiBOYW1lPSJJUFJDYWwiIEFsaWFzPSJJUFIgQ2FsY3VsYXRpb24iIEljb249IklQUkNhbCIgLz4NCiAgICAgICAgPC9Hcm91cD4NCg0KICAgICAgICA8R3JvdXAgTmFtZT0iV2R0RGF0YVByZXByb2Nlc3MiIEFsaWFzPSJEYXRhIFByZXByb2Nlc3NpbmciIFZpc2libGU9IjAiPg0KICAgICAgICAgICAgPENtZCBJRD0iNjEwMSIgQm91bmRzPSIwLDAsMiwxIiBOYW1lPSJXZHREYXRhQXNzbiIgQWxpYXM9IkRhdGEgTm9ybWFsaXphdGlvbiIgRXh0SW5mbz0iSVBSIiBJY29uPSJJUFJBbmFsIiAgVmlzaWJsZT0iMCIvPg0KICAgICAgICAgICAgPENtZCBJRD0iNjEwMiIgQm91bmRzPSIwLDEsMiwxIiBOYW1lPSJXZHRPdGhlciIgQWxpYXM9Ik90aGVycyIgSWNvbj0iV2R0T3RoZXIiIFZpc2libGU9IjAiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI2MTAzIiBCb3VuZHM9IjAsMywyLDEiIE5hbWU9IldkdFdNRiIgQWxpYXM9IldlbGxib3JlIE11bHRpcGhhc2UgRmxvdyIgSWNvbj0iV2R0V01GIiAgVmlzaWJsZT0iMCIvPg0KICAgICAgICAgICAgPENtZCBJRD0iNjEwNCIgQm91bmRzPSIwLDQsMiwxIiBOYW1lPSJXZHRDaG9rZSIgQWxpYXM9IkNob2tlIEZsb3ciIEljb249IldkdENob2tlIiAgVmlzaWJsZT0iMCIvPg0KICAgICAgICA8L0dyb3VwPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJJUFIiIEFsaWFzPSJQcm9kdWN0aXZpdHkgQW5hbHlzaXMiPg0KICAgICAgICAgICAgPENtZCBJRD0iNjIwMSIgQm91bmRzPSIwLDAsMiwxIiBOYW1lPSJXZHRJUFJDYWwiIEFsaWFzPSJSZXNlcnZvaXIgUHJvZHVjdGl2aXR5IENhbGN1bGF0aW9uIiBJY29uPSJJUFJDYWwiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI2MjAyIiBCb3VuZHM9IjAsMSwyLDEiIE5hbWU9IldlbGxQZHR5IiBBbGlhcz0iSW50ZWdyYXRlZCBQcm9kdWN0aXZpdHkiIEljb249IldlbGxQZHR5IiAgVmlzaWJsZT0iMCIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjYyMDMiIEJvdW5kcz0iMCwyLDIsMSIgTmFtZT0iV2R0SVBSRXh0IiBBbGlhcz0iUHJvZHVjdGl2aXR5IFdlbGwgVGVzdFtFeHRlbmRlZF0iIEljb249IklQUkV4dCIvPg0KICAgICAgICAgICAgPENtZCBJRD0iNjIwNCIgQm91bmRzPSIwLDMsMiwxIiBOYW1lPSJXZHRJUFJBbmFsIiBBbGlhcz0iUmVzZXJ2b2lyIFByb2R1Y3Rpdml0eSBBbmFseXNpcyIgSWNvbj0iSVBSQW5hbCIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjYyMDUiIEJvdW5kcz0iMCw0LDIsMSIgTmFtZT0iV2VsbEludGVnQW5hbCIgQWxpYXM9IkNvbXByZWhlbnNpdmUgQW5hbHlzaXMiIEljb249IldlbGxJbnRlZ0FuYWwiIFZpc2libGU9IjAiIC8+DQogICAgICAgIDwvR3JvdXA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9IklQUiIgQWxpYXM9IlByb2R1Y3Rpdml0eSBDYWxjdWxhdGlvbiI+DQogICAgICAgICAgICA8Q21kIElEPSI2MzAxIiBCb3VuZHM9IjAsMCwyLDEiIE5hbWU9IldkdENhbCIgQWxpYXM9IkNhbGN1bGF0aW9uIiBJY29uPSJSdW5FeCIgLz4NCiAgICAgICAgPC9Hcm91cD4NCg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJKb2JzIiBBbGlhcz0iUmVzdWx0IE1hbmFnZW1lbnQiPg0KICAgICAgICAgICAgPENtZCBJRD0iMTAwOCIgQm91bmRzPSIwLDAiIE5hbWU9IlJzdExvYWQiIEFsaWFzPSJMb2FkIFJlc3VsdHMiIEljb249IkxvYWRKb2JzIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMTAwOSIgQm91bmRzPSIxLDAiIE5hbWU9IlJzdFNhdmUiIFR5cGU9IjEiIEV4dE5hbWVzPSJSc3RTYXZlQ3VyO1JzdFNhdmVBbGwiIEV4dEluZm89IlNhdmUgQ3VycmVudCBSZXN1bHQ7U2F2ZSBBbGwgUmVzdWx0cyIgQWxpYXM9IlNhdmUgUmVzdWx0cyIgSWNvbj0iU2F2ZUpvYnMiIC8+DQogICAgICAgIDwvR3JvdXA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9IldpbmRvdyIgQWxpYXM9IldpbmRvdyBEaXNwbGF5Ij4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkwMDIiIEJvdW5kcz0iMCwwIiBOYW1lPSJWaXNpYmxlTW9kZWxzIiBBbGlhcz0iTW9kZWwgV2luZG93IiBJY29uPSJWaXNpYmxlTW9kZWxzIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTAwMyIgQm91bmRzPSIxLDAiIE5hbWU9IlZpc2libGVQYXJhbWV0ZXJzIiBBbGlhcz0iUGFyYW1ldGVyIFdpbmRvdyIgSWNvbj0iVmlzaWJsZVBhcmFtZXRlcnMiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI5MTAxIiBCb3VuZHM9IjAsMSIgTmFtZT0iVmlzaWJsZUFuYWxCYXNpYyIgQWxpYXM9IkJhc2ljIEluZm8iIEljb249IklucHV0QmFzaWMiICAgVmlzaWJsZT0iMCIvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTEwMiIgQm91bmRzPSIwLDEiIE5hbWU9IlZpc2libGVBbmFsUFZUIiBBbGlhcz0iUFZUIERhdGEiIEljb249IklucHV0Rmx1aWQiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI5MTAzIiBCb3VuZHM9IjAsMiIgTmFtZT0iVmlzaWJsZUFuYWxEaWZmIiBBbGlhcz0iRElGRiBEYXRhIiBJY29uPSJJbnB1dEZsdWlkIiAgIFZpc2libGU9IjAiLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkxMDQiIEJvdW5kcz0iMSwxIiBOYW1lPSJWaXNpYmxlQW5hbFBzZXUiIEFsaWFzPSJQc2V1ZG8gUHJlc3N1cmUgRGF0YSIgSWNvbj0iSW5wdXRGbHVpZCIgLz4NCiAgICAgICAgPC9Hcm91cD4NCg0KDQogICAgPC9UYWI+DQoNCiAgICA8VGFiIElEPSI2IiBOYW1lPSJBZHZhbmNlZEZ1bmN0aW9uIiBBbGlhcz0iQWR2YW5jZWQiID4NCg0KICAgICAgICA8R3JvdXAgTmFtZT0iRGVzaWduIiBBbGlhcz0iV2VsbCBUZXN0IERlc2lnbiI+DQogICAgICAgICAgICA8Q21kIElEPSI2MDAxIiBCb3VuZHM9IjAsMCwyLDEiIE5hbWU9IlRlc3REZXNpZ24iIEFsaWFzPSJXZWxsIFRlc3QgRGVzaWduIiBJY29uPSJUZXN0RGVzaWduIiBFeHRJbmZvPSJQRiIgIC8+DQogICAgICAgICAgICA8Q21kIElEPSIzMDA0IiBCb3VuZHM9IjAsMSwyLDEiIE5hbWU9IkFuYWxGbG93U2VnIiBBbGlhcz0iRmxvdyBQZXJpb2QgQW5hbHlzaXMiIEljb249IkZsb3dQZXJpb2QiIC8+DQogICAgICAgICAgICA8Q21kIElEPSIzMDA1IiBCb3VuZHM9IjAsMiwyLDEiIE5hbWU9IkFuYWxPdGhlcnMiIEFsaWFzPSJDaGFyYWN0ZXJpc3RpYyBTZWdtZW50IEFuYWx5c2lzIiBUeXBlPSIxIiBFeHROYW1lcz0iQ2hhcnRUO0NoYXJ0U3FydFQ7Q2hhcnQyNVQ7Q2hhcnQ1VCIgRXh0SW5mbz0iQ2hhcnQgVDtDaGFydCBTcXJ0KFQpO0NoYXJ0IDAuMjVUO0NoYXJ0IC0wLjVUIiBJY29uPSJBc3Npc0FuYWwiIC8+DQogICAgICAgICAgICA8Q21kIElEPSIzMDA5IiBCb3VuZHM9IjAsMywyLDEiIE5hbWU9IkFuYWxEaXN0cmkiIEFsaWFzPSJEaXN0cmlidXRpb24gQ2hhcnQiIFR5cGU9IjEiIEV4dE5hbWVzPSJDaGFydERlbjtDaGFydFZpcyIgRXh0SW5mbz0iQ29uY2VudHJhdGlvbiBEaXN0cmlidXRpb247VmlzY29zaXR5IERpc3RyaWJ1dGlvbiIgSWNvbj0iQW5hbERpc3RyaSIgLz4NCg0KICAgICAgICA8L0dyb3VwPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJEYXRhRml0IiBBbGlhcz0iSW50ZXJwcmV0YXRpb24gRml0dGluZyI+DQoNCiAgICAgICAgICAgIDxDbWQgSUQ9IjMxMDUiIEJvdW5kcz0iMCwwLDIsMSIgTmFtZT0iRGVjb252b2x2IiBBbGlhcz0iRGVjb252b2x1dGlvbiIgSWNvbj0iRGVjb252b2x2IiBWaXNpYmxlPSIwIi8+DQogICAgICAgICAgICA8Q21kIElEPSIzMTAxIiBCb3VuZHM9IjAsMSwyLDEiIE5hbWU9IkZpdE1vZGVsIiBBbGlhcz0iQW5hbHl0aWNhbCBTb2x1dGlvbiIgSWNvbj0iRml0TW9kZWwiIC8+DQogICAgICAgICAgICA8Q21kIElEPSIzMTA0IiBCb3VuZHM9IjAsMiwyLDEiIE5hbWU9Im5tRml0TW9kZWwiIEFsaWFzPSJOdW1lcmljYWwgU29sdXRpb24iIEljb249IkZpdE1vZGVsIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMzEwMiIgQm91bmRzPSIwLDMsMiwxIiBOYW1lPSJBdXRvRml0IiBBbGlhcz0iQXV0byBGaXR0aW5nIiBJY29uPSJBdXRvRml0IiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMzEwMyIgQm91bmRzPSIwLDQsMiwxIiBOYW1lPSJQbGF0ZUZpdCIgQWxpYXM9IlNlbnNpdGl2aXR5IEFuYWx5c2lzIiBJY29uPSJQbGF0ZUZpdCIgLz4NCiAgICAgICA8L0dyb3VwPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJBSVRlc3QiIEFsaWFzPSJJbnRlbGxpZ2VudCBXZWxsIFRlc3QoRGVidWcpIj4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjM5MDEiIEJvdW5kcz0iMCwwLDIsMSIgTmFtZT0iTW9kZWxDbGFzc2lmeSIgQWxpYXM9Ik1vZGVsIFJlY29nbml0aW9uIiBJY29uPSJNb2RlbENsYXNzaWZ5IiAvPg0KICAgICAgICA8L0dyb3VwPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJSZWxhdGl2ZVRvb2wiIEFsaWFzPSJSZWxhdGVkIFRvb2xzIiBWaXNpYmxlPSIwIj4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjMyMDEiIEJvdW5kcz0iMCwwIiBOYW1lPSJUaW1lIiBBbGlhcz0iVGltZSIgSWNvbj0iVGltZSIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjMyMDIiIEJvdW5kcz0iMSwwIiBOYW1lPSJTaG93TW9kZWxDaGFydHMiIEFsaWFzPSJNb2RlbCIgSWNvbj0iU2hvd01vZGVsQ2hhcnRzIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMzIwMyIgQm91bmRzPSIwLDEiIE5hbWU9IlNob3dNb2RlbFNrZXRjaCIgQWxpYXM9IlRoZW9yeSIgSWNvbj0iU2hvd01vZGVsU2tldGNoIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMzIwNCIgQm91bmRzPSIxLDEiIE5hbWU9IlNhdmVBc01vZGVsU2tldGNoIiBBbGlhcz0iU2F2ZSBBcyBTY2hlbWF0aWMiIEljb249IlNhdmVBc01vZGVsU2tldGNoIiAvPg0KICAgICAgIDwvR3JvdXA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9IlRvb2xTIiBBbGlhcz0iRXh0ZW5kZWQgRnVuY3Rpb25zIiAgVmlzaWJsZT0iMCI+DQogICAgICAgICAgICA8Q21kIElEPSI5ODAxIiBCb3VuZHM9IjAsMCwyLDEiIE5hbWU9IkZsb3dUb1MiIEFsaWFzPSJSYXRlIHRvIFNraW4gRmFjdG9yIiBJY29uPSJGbG93VG9TIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTIwMSIgQm91bmRzPSIwLDEsMiwxIiBOYW1lPSJNaXhWaXNjb3NpdHkiIEFsaWFzPSJNaXhlZCBWaXNjb3NpdHkiIEljb249Ik1peFZpc2Nvc2l0eSIgLz4NCiAgICAgICA8L0dyb3VwPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJKb2JzIiBBbGlhcz0iUmVzdWx0IE1hbmFnZW1lbnQiIFZpc2libGU9IjAiPg0KICAgICAgICAgICAgPENtZCBJRD0iMTAwOCIgQm91bmRzPSIwLDAiIE5hbWU9IlJzdExvYWQiIEFsaWFzPSJMb2FkIFJlc3VsdHMiIEljb249IkxvYWRKb2JzIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMTAwOSIgQm91bmRzPSIxLDAiIE5hbWU9IlJzdFNhdmUiIFR5cGU9IjEiIEV4dE5hbWVzPSJSc3RTYXZlQ3VyO1JzdFNhdmVBbGwiIEV4dEluZm89IlNhdmUgQ3VycmVudCBSZXN1bHQ7U2F2ZSBBbGwgUmVzdWx0cyIgQWxpYXM9IlNhdmUgUmVzdWx0cyIgSWNvbj0iU2F2ZUpvYnMiIC8+DQogICAgICAgIDwvR3JvdXA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9IldpbmRvdyIgQWxpYXM9IldpbmRvdyBEaXNwbGF5IiBWaXNpYmxlPSIwIj4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkwMDIiIEJvdW5kcz0iMCwwIiBOYW1lPSJWaXNpYmxlTW9kZWxzIiBBbGlhcz0iTW9kZWwgV2luZG93IiBJY29uPSJWaXNpYmxlTW9kZWxzIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTAwMyIgQm91bmRzPSIxLDAiIE5hbWU9IlZpc2libGVQYXJhbWV0ZXJzIiBBbGlhcz0iUGFyYW1ldGVyIFdpbmRvdyIgSWNvbj0iVmlzaWJsZVBhcmFtZXRlcnMiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI5MTAxIiBCb3VuZHM9IjAsMSIgTmFtZT0iVmlzaWJsZUFuYWxCYXNpYyIgQWxpYXM9IkJhc2ljIEluZm8iIEljb249IklucHV0QmFzaWMiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI5MTAyIiBCb3VuZHM9IjEsMSIgTmFtZT0iVmlzaWJsZUFuYWxQVlQiIEFsaWFzPSJQVlQgRGF0YSIgSWNvbj0iSW5wdXRGbHVpZCIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkxMDMiIEJvdW5kcz0iMCwyIiBOYW1lPSJWaXNpYmxlQW5hbERpZmYiIEFsaWFzPSJESUZGIERhdGEiIEljb249IklucHV0Rmx1aWQiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI5MTA0IiBCb3VuZHM9IjEsMiIgTmFtZT0iVmlzaWJsZUFuYWxQc2V1IiBBbGlhcz0iUHNldWRvIFByZXNzdXJlIERhdGEiIEljb249IklucHV0Rmx1aWQiIC8+DQogICAgICAgIDwvR3JvdXA+DQoNCiAgICA8L1RhYj4NCg0KICAgIDxUYWIgSUQ9IjciIE5hbWU9IlN5c1Rvb2wiIEFsaWFzPSJTeXN0ZW0gQ29uZmlndXJhdGlvbiBUb29scyhUKSIgVmlzaWJsZT0iMCIgPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJTeXNUb29sIiBBbGlhcz0iQ29uZmlndXJhdGlvbiBUb29scyI+DQogICAgICAgICAgICA8Q21kIElEPSI3MDAxIiBCb3VuZHM9IjAsMSwyLDEiIE5hbWU9IlN5c1Rvb2xzIiBBbGlhcz0iU3lzdGVtIENvbmZpZ3VyYXRpb24gVG9vbHMiIEljb249IlN5c1Rvb2xzIiAgLz4NCiAgICAgICAgPC9Hcm91cD4NCg0KICAgICAgICA8R3JvdXAgTmFtZT0iTW9kZWxNYW5hZ2VyIiBBbGlhcz0iTW9kZWwgTWFuYWdlbWVudCI+DQogICAgICAgICAgICA8Q21kIElEPSI3MDAyIiBCb3VuZHM9IjAsMCwyLDEiIE5hbWU9Ik1vZGVsU2NhbiIgQWxpYXM9Ik1vZGVsIFZpZXciIEljb249Ik1vZGVsU2NhbiIgLz4NCiAgICAgICAgPC9Hcm91cD4NCg0KICAgIDwvVGFiPg0KDQogICAgPFRhYiBJRD0iOCIgTmFtZT0iUmVzdWx0IiBBbGlhcz0iUmVzdWx0cyIgPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJKb2JzIiBBbGlhcz0iUmVzdWx0IE1hbmFnZW1lbnQiPg0KICAgICAgICAgICAgPENtZCBJRD0iMTAwOCIgQm91bmRzPSIwLDAiIE5hbWU9IlJzdExvYWQiIEFsaWFzPSJMb2FkIFJlc3VsdHMiIEljb249IkxvYWRKb2JzIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMTAwOSIgQm91bmRzPSIxLDAiIE5hbWU9IlJzdFNhdmUiIFR5cGU9IjEiIEV4dE5hbWVzPSJSc3RTYXZlQ3VyO1JzdFNhdmVBbGwiIEV4dEluZm89IlNhdmUgQ3VycmVudCBSZXN1bHQ7U2F2ZSBBbGwgUmVzdWx0cyIgQWxpYXM9IlNhdmUgUmVzdWx0cyIgSWNvbj0iU2F2ZUpvYnMiIC8+DQogICAgICAgIDwvR3JvdXA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9IlJlc0NvbXBhcmUiIEFsaWFzPSJSZXN1bHQgQ29tcGFyaXNvbiI+DQogICAgICAgICAgICA8Q21kIElEPSI4MDAzIiBCb3VuZHM9IjAsMCwyLDEiIE5hbWU9IlJlc0NvbXBhcmUiIEFsaWFzPSJSZXN1bHQgQ29tcGFyaXNvbiIgSWNvbj0iUmVzQ29tcGFyZSIgIC8+DQogICAgICAgIDwvR3JvdXA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9IlByaW50IiBBbGlhcz0iUmVwb3J0IFByaW50aW5nIj4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjgwMDEiIEJvdW5kcz0iMCwwIiBOYW1lPSJSZXBvcnRDb25maWciIEFsaWFzPSJSZXBvcnQgU2V0dGluZ3MiIEljb249InJlcG9ydENvbmZpZyIgIC8+DQogICAgICAgICAgICA8Q21kIElEPSI4MDA0IiBCb3VuZHM9IjEsMCIgTmFtZT0iUHJpbnRQcmV2aWV3IiBBbGlhcz0iUmVwb3J0IFByZXZpZXciIEljb249IlByZVByaW50IiAgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjgwMDIiIEJvdW5kcz0iMCwxIiBOYW1lPSJQcmludCIgQWxpYXM9IlByaW50KEluY2x1ZGUgUERGKSIgSWNvbj0iUHJpbnQiICAvPg0KICAgICAgICAgICAgPENtZCBJRD0iODAwNSIgQm91bmRzPSIxLDEiIE5hbWU9IkV4cG9ydFdvcmQiIEFsaWFzPSJFeHBvcnQoV29yZCkiIEljb249IldvcmQxNiIgIC8+DQogICAgICAgIDwvR3JvdXA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9IldpbmRvdyIgQWxpYXM9IldpbmRvdyBEaXNwbGF5IiBWaXNpYmxlPSIwIj4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkwMDMiIEJvdW5kcz0iMCwwLDIsMSIgTmFtZT0iVmlzaWJsZVBhcmFtZXRlcnMiIEFsaWFzPSJQYXJhbWV0ZXIgV2luZG93IiBJY29uPSJWaXNpYmxlUGFyYW1ldGVycyIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkwMDQiIEJvdW5kcz0iMCwxLDIsMSIgTmFtZT0iVmlzaWJsZVB0eXMiIEFsaWFzPSJQcm9wZXJ0eSBXaW5kb3ciIEljb249IlByb3BlcnR5V2luZG93IiAvPg0KDQogICAgICAgIDwvR3JvdXA+DQoNCiAgICA8L1RhYj4NCg0KICAgIDxUYWIgSUQ9IjkiIE5hbWU9IldpbmRvdyIgQWxpYXM9IldpbmRvdyIgPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJXaW5kb3ciIEFsaWFzPSJCYXNpYyI+DQogICAgICAgICAgICA8Q21kIElEPSI5MDAxIiBCb3VuZHM9IjAsMCwyLDEiIE5hbWU9IlZpc2libGVQcm9qVHJlZURhIiBBbGlhcz0iUHJvamVjdCBUcmVlIiBJY29uPSJQcm9qVHJlZSIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkwMDgiIEJvdW5kcz0iMCwxLDIsMSIgTmFtZT0iVmlzaWJsZVByb2pUcmVlSmIiIEFsaWFzPSJBbmFseXNpcyBUcmVlIiBJY29uPSJQcm9qVHJlZSIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkwMDkiIEJvdW5kcz0iMCwyLDIsMSIgTmFtZT0iVmlzaWJsZVByb2pUcmVlUnMiIEFsaWFzPSJSZXN1bHQgVHJlZSIgSWNvbj0iUHJvalRyZWUiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI5MDAyIiBCb3VuZHM9IjAsMyIgTmFtZT0iVmlzaWJsZU1vZGVscyIgQWxpYXM9Ik1vZGVsIFdpbmRvdyIgSWNvbj0iVmlzaWJsZU1vZGVscyIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkwMDMiIEJvdW5kcz0iMSwzIiBOYW1lPSJWaXNpYmxlUGFyYW1ldGVycyIgQWxpYXM9IlBhcmFtZXRlciBXaW5kb3ciIEljb249IlZpc2libGVQYXJhbWV0ZXJzIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTAwNCIgQm91bmRzPSIwLDQiIE5hbWU9IlZpc2libGVQdHlzIiBBbGlhcz0iUHJvcGVydHkgV2luZG93IiBJY29uPSJQcm9wZXJ0eVdpbmRvdyIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkwMDUiIEJvdW5kcz0iMSw0IiBOYW1lPSJWaXNpYmxlTG9ncyIgQWxpYXM9IkxvZyBXaW5kb3ciIEljb249IlZpc2libGVMb2dzIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTAwNiIgQm91bmRzPSIwLDUiIE5hbWU9IlN0YWNrZWRQcm9qZWN0IiBBbGlhcz0iUHJvamVjdCBXaW5kb3ciIEljb249IlN0YWNrZWRQcm9qZWN0IiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTAwNyIgQm91bmRzPSIxLDUiIE5hbWU9IlN0YWNrZWRNZGkiIEFsaWFzPSJBbmFseXNpcyBXaW5kb3ciIEljb249IlN0YWNrZWRNZGkiIC8+DQogICAgICAgIDwvR3JvdXA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9IldpbmRvd0xheW91dCIgQWxpYXM9IldpbmRvdyBMYXlvdXQiPg0KICAgICAgICAgICAgPENtZCBJRD0iOTAxMSIgQm91bmRzPSIwLDAiIE5hbWU9IldpbmRvd0xheW91dEgiIEljb25Pbmx5PSIxIiBUaXBzPSJIb3Jpem9udGFsIExheW91dCIgSWNvbj0iV2luZG93TGF5b3V0SCIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkwMTIiIEJvdW5kcz0iMSwwIiBOYW1lPSJXaW5kb3dMYXlvdXRWIiBJY29uT25seT0iMSIgVGlwcz0iVmVydGljYWwgTGF5b3V0IiBJY29uPSJXaW5kb3dMYXlvdXRWIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTAxMyIgQm91bmRzPSIwLDEiIE5hbWU9IldpbmRvd0xheW91dFQiIEljb25Pbmx5PSIxIiBUaXBzPSJUaWxlIExheW91dCIgSWNvbj0iV2luZG93TGF5b3V0VCIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkwMTQiIEJvdW5kcz0iMSwxIiBOYW1lPSJXaW5kb3dMYXlvdXRDIiBJY29uT25seT0iMSIgVGlwcz0iQ29sbGFwc2UgTGF5b3V0IiBJY29uPSJXaW5kb3dMYXlvdXRDIiAvPg0KICAgICAgICA8L0dyb3VwPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJDbG9zZSIgQWxpYXM9IkNsb3NlIj4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkwMjEiIEJvdW5kcz0iMCwwIiBOYW1lPSJDbG9zZUN1clduZCIgQWxpYXM9IkNsb3NlIEN1cnJlbnQiIEljb249IkNsb3NlQWxsV2luZG93IiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTAyMiIgQm91bmRzPSIxLDAiIE5hbWU9IkNsb3NlQWxsV25kcyIgQWxpYXM9IkNsb3NlIEFsbCIgSWNvbj0iQ2xvc2VBbGxXaW5kb3ciIC8+DQogICAgICAgICAgICA8Q21kIElEPSI5MDIzIiBCb3VuZHM9IjAsMSIgTmFtZT0iUHJldlduZCIgQWxpYXM9IlByZXZpb3VzIiBJY29uT25seT0iMSIgSWNvbj0iVXAiIFRpcHM9IlByZXZpb3VzIFdpbmRvdyIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkwMjQiIEJvdW5kcz0iMSwxIiBOYW1lPSJOZXh0V25kIiBBbGlhcz0iTmV4dCIgSWNvbk9ubHk9IjEiIEljb249IkRvd24iIFRpcHM9Ik5leHQgV2luZG93IiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTAyNSIgQm91bmRzPSIwLDIsMiwxIiBUeXBlPSI3IiBOYW1lPSJMaXN0V3hXbmRzIiBBbGlhcz0iV2luZG93cyIgLz4NCiAgICAgICAgPC9Hcm91cD4NCg0KICAgIDwvVGFiPg0KDQogICAgPFRhYiBJRD0iMTAiIE5hbWU9IkhlbHAiIEFsaWFzPSJIZWxwIiA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9IkhlbHAiIEFsaWFzPSJIZWxwIj4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjEwMDAxIiBCb3VuZHM9IjAsMCwyLDEiIE5hbWU9IkxvZ1ZpZXciIEFsaWFzPSJMb2cgVmlldyhMKSIgSWNvbj0iTG9nVmlldyIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjEwMDAyIiBCb3VuZHM9IjAsMSwyLDEiIE5hbWU9IkhlbHAiIEFsaWFzPSJIZWxwKEgpIiBJY29uPSJIZWxwIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMTAwMDgiIEJvdW5kcz0iMCwyLDIsMSIgTmFtZT0iVXBkYXRlTGlzdHMiIEFsaWFzPSJVcGRhdGUgTGlzdHMoSSkiIEljb249IlVwZGF0ZUxpc3RzIiAvPg0KICAgICAgICA8L0dyb3VwPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJMYW5nIiBBbGlhcz0iTGFuZ3VhZ2UiPg0KICAgICAgICAgICA8Q21kIElEPSIxMDAwOSIgQm91bmRzPSIwLDAsMiwxIiBOYW1lPSJMYW5nU3dhcCIgQWxpYXM9IlN3YXAgbGFuZ3VhZ2UiIEljb249IkxhbmdTd2FwIiAvPg0KICAgICAgICA8L0dyb3VwPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJBYm91dCIgQWxpYXM9IkFib3V0Ij4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjEwMDAzIiBCb3VuZHM9IjAsMCwyLDEiIE5hbWU9IkFib3V0IiBBbGlhcz0iQWJvdXQoQSkiIEljb249IldUQUlBYm91dCIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjEwMDA0IiBCb3VuZHM9IjEsMCIgTmFtZT0iQWJvdXRRdCIgQWxpYXM9IkFib3V0IFF0KFEpIiBJY29uPSJRdCIgVmlzaWJsZT0iMCIgLz4NCiAgICAgICAgPC9Hcm91cD4NCg0KICAgICAgICA8R3JvdXAgTmFtZT0iTG9naW4iIEFsaWFzPSJMb2dpbihEZWJ1ZykiPg0KICAgICAgICAgICAgPENtZCBJRD0iMTAwMDciIEJvdW5kcz0iMCwwIiBOYW1lPSJSZWdpc3RlciIgQWxpYXM9IihEZWJ1ZylTb2Z0d2FyZSBSZWdpc3RyYXRpb24oUikiIEljb249IlJlZ2lzdGVyIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMTAwMDUiIEJvdW5kcz0iMSwwIiBOYW1lPSJMb2dpbiIgQWxpYXM9IihEZWJ1ZylVc2VyIExvZ2luKFUpIiBJY29uPSJMb2dpbiIgLz4NCiAgICAgICAgPC9Hcm91cD4NCg0KICAgICAgICA8R3JvdXAgTmFtZT0iRGVidWciIEFsaWFzPSJEZWJ1ZyhEZWJ1ZykiPg0KICAgICAgICAgICAgPENtZCBJRD0iMTAwMDYiIEJvdW5kcz0iMCwwLDIsMSIgTmFtZT0iKERlYnVnKSBTdW0gUGFyYW1ldGVycyIgQWxpYXM9IihEZWJ1ZylTdW1tYXJpemUgTW9kZWwgUGFyYW1ldGVycyIgSWNvbj0iU3VtUGFyYSIgLz4NCiAgICAgICA8L0dyb3VwPg0KICAgIDwvVGFiPg0KDQo8L1JpYmJvbj4NCg==
\ No newline at end of file
+77u/PD94bWwgcup_mpadmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4NCg0KPCEtLSDnvJbovpHkvbwzy/nlKggWE1MU3B5IHYyMDA2IFUgKGh0dHA6Ly93d3cuYWx0b3ZhLmNvbSkg55SxIGFueSAoYW55KSAtLT4NCjwhLS0qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqLS0+DQo8IS0tICAgIOacrOaWh+aho+eahOebrueahOaYr+W7uueri1dUQUnova/ku7bns7vnu5/nmoToj5zljZXlsYLmrKHlhbPns7so6ZKI5a+5UmliYm9u5qih5byPKSAgICAgICAgICAgICAgICAgICAgICAgLS0+DQo8IS0tICAgIEF1dGhvcihzKTogd2FuZ3pnICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC0tPg0KPCEtLSAgICBEYXRlOiAyMDI0MDcxOCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAtLT4NCjwhLS0qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqLS0+DQoNCjwhLS0qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqLS0+DQo8IS0tDQogICAgVGFiIOe6p+WIqw0KICAgICAgICBJRDogICAgICAgICAg5ZSv5LiA5qCH6K+GDQogICAgICAgIE5hbWXvvJogICAgICAg5ZCN56ew77yM6YCa5bi46Iux5paHDQogICAgICAgIEFsaWFz77yaICAgICAg5Yir5ZCN77yM6YCa5bi45Lit5paHDQogICAgICAgIEZpbGVNb2RlOiAgICDmmK/lkKbmlofku7ZNZW515qih5byP77yMMSBvciAwDQogICAgICAgIFZpc2libGXvvJogICAg5piv5ZCm5Y+v6KeB77yMMSBvciAwDQogICAgICAgIFRpcHPvvJogICAgICAg6L6F5Yqp6K+05piODQoNCiAgICAgICAgR3JvdXAg57qn5YirDQogICAgICAgICAgICBOYW1l77yaICAgICAgIOWQjeensO+8jOmAmuW4uOiLseaWhw0KICAgICAgICAgICAgQWxpYXPvvJogICAgICDliKvlkI3vvIzpgJrluLjkuK3mlocNCg0KICAgICAgICAgICAgQ21kIOe6p+WIqw0KICAgICAgICAgICAgICAgIElEOiAgICAgICAgICDllK/kuIDmoIfor4YNCiAgICAgICAgICAgICAgICBUeXBlOiAgICAgICAg5a+55bqU5o6n5Lu257G75Z6LOg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAw4oCU4oCU6buY6K6kQnV0dG9uDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIDHigJTigJTluKbkuIvmi4noj5zljZVCdXR0b24NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMuKAlOKAlENvbWJvQm94DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIDPigJTigJRDaGVja0JveA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICA04oCU4oCUUmFkaW9CdXR0b24NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgNeKAlOKAlFRleHQNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgNuKAlOKAlExhYmVsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIDfigJTigJRMaXN0V2lkZ2V0DQogICAgICAgICAgICAgICAgTmFtZe+8miAgICAgICDlkI3np7DvvIzpgJrluLjoi7HmlocNCiAgICAgICAgICAgICAgICBBbGlhc++8miAgICAgIOWIq+WQje+8jOmAmuW4uOS4reaWhw0KICAgICAgICAgICAgICAgIEljb27vvJogICAgICAg5Zu+5qCHDQogICAgICAgICAgICAgICAgU2hvcnRLZXnvvJogICDlv6vmjbfplK4NCiAgICAgICAgICAgICAgICBCb3VuZHM6ICAgICAg5L2N572u5L+h5oGv77yM5YWo5piv5pW05pWw77yM5ZyoR3JpZExheW91dOS4rQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoMCwwLDEsMikgKDAsMCkg5YiG5Yir5Li6eHl3aA0KICAgICAgICAgICAgICAgIEV4dEluZm86ICAgICDmianlsZXkv6Hmga/vvIzlpoLmk43kvZzlr7nosaHnmoTooajlkI0s5LiL5ouJ6YCJ6aG5562JDQogICAgICAgICAgICAgICAgRXh0TmFtZXM6ICAgIOaJqeWxleS/oeaBr+WvueW6lOeahE5hbWXvvIzlpoLkuIvmi4lidXR0b27lr7nlupTnmoROYW1lDQogICAgICAgICAgICAgICAgVGlwc++8miAgICAgICDovoXliqnor7TmmI4NCi0tPg0KPCEtLSoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiotLT4NCg0KPFJpYmJvbj4NCg0KICAgIDxUYWIgSUQ9IjEiIE5hbWU9IlByb2pNYW5hZ2VyIiBBbGlhcz0iUHJvaiBNYW5hZ2VyIiBGaWxlTW9kZT0iMSIgPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJQcm9qZWN0IiBBbGlhcz0iRmlsZSI+DQogICAgICAgICAgICA8Q21kIElEPSIxMDAwIiBOYW1lPSJBcHBIb21lIiBBbGlhcz0iIiBJY29uPSJBcHBIb21lMTI4IiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iLTEiIE5hbWU9IlNlcGFyYXRvciIgQWxpYXM9IlNlcGFyYXRvciIgVGlwcz0iIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMTAwMSIgTmFtZT0iUHJvak5ldyIgQWxpYXM9Ik5ldyBwcm9qZWN0IiBTaG9ydEtleT0iQ3RybCtOIiBJY29uPSJOZXdQcm9qIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMTAwMiIgTmFtZT0iUHJvak9wZW4iIEFsaWFzPSJPcGVuIHByb2plY3QiIFNob3J0S2V5PSJDdHJsK08iIEljb249Ik9wZW5Qcm9qIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMTAwMyIgTmFtZT0iUHJvakNsb3NlIiBBbGlhcz0iQ2xvc2UgcHJvamVjdCIgSWNvbj0iQ2xvc2VQcm9qIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iLTEiIE5hbWU9IlNlcGFyYXRvciIgQWxpYXM9IlNlcGFyYXRvciIgVGlwcz0iIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMTAwNSIgTmFtZT0iUHJvalNhdmUiIEFsaWFzPSJTYXZlIHByb2plY3QiIFNob3J0S2V5PSJDdHJsK1MiIEljb249IlNhdmVQcm9qIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMTAwNiIgTmFtZT0iUHJvalNhdmVBcyIgQWxpYXM9IlNhdmUgcHJvamVjdCBhcyIgSWNvbj0iU2F2ZWFzIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMTAwNyIgTmFtZT0iUHJvakNvbmZpZyIgQWxpYXM9IlByb2plY3RJbmZvIiBJY29uPSJQcm9qSW5mbyIgLz4NCg0KICAgICAgICAgICAgPENtZCBJRD0iLTEiIE5hbWU9IlNlcGFyYXRvciIgQWxpYXM9IlNlcGFyYXRvciIgVGlwcz0iIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMTAwMDIiIE5hbWU9IkhlbHAiIEFsaWFzPSJIZWxwIiBJY29uPSJIZWxwIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMTAwMDMiIE5hbWU9IkFib3V0IiBBbGlhcz0iQWJvdXQiIEljb249IldUQUlBYm91dCIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjEwMDA4IiBOYW1lPSJVcGRhdGVMaXN0cyIgQWxpYXM9IlVwZGF0ZSBsaXN0cyIgSWNvbj0iVXBkYXRlTGlzdHMiIC8+DQogICAgICAgICAgICA8Q21kIElEPSItMSIgTmFtZT0iU2VwYXJhdG9yIiBBbGlhcz0iU2VwYXJhdG9yIiBUaXBzPSIiIC8+DQogICAgICAgICAgICA8Q21kIElEPSIxMDEwIiBOYW1lPSJBcHBRdWl0IiBBbGlhcz0iUXVpdChYKSIgSWNvbj0iQ2xvc2UiIC8+DQogICAgICAgIDwvR3JvdXA+DQogICAgPC9UYWI+DQoNCiAgICA8VGFiIElEPSIwIiBOYW1lPSJXZWxDb21lIiBBbGlhcz0iU3RhcnQiID4NCg0KICAgICAgICA8R3JvdXAgTmFtZT0iRGF0YU1hbmFnZXIiIEFsaWFzPSJEYXRhIj4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjEwOTkiIEJvdW5kcz0iMCwwLDIsMSIgTmFtZT0iV2VsbE5ldyIgQWxpYXM9Ik5ldyB3ZWxsIiBJY29uPSJXZWxsTmV3IiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMjAwNSIgQm91bmRzPSIwLDEsMiwxIiBOYW1lPSJEYXRhUmF0ZSIgQWxpYXM9IlJhdGUiIEV4dEluZm89IlBfREFUQV9HQVVHRV9GIiBJY29uPSJSYXRlRGF0YSIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjIwMDYiIEJvdW5kcz0iMCwyLDIsMSIgTmFtZT0iRGF0YVByZSIgQWxpYXM9IlByZXNzdXJlIiBFeHRJbmZvPSJQX0RBVEFfR0FVR0VfUCIgSWNvbj0iUHJlc3N1cmVEYXRhIiAvPg0KICAgICAgICA8L0dyb3VwPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJBbmFsRWRpdCIgQWxpYXM9IkFuYWwiPg0KICAgICAgICAgICAgPENtZCBJRD0iMzAwNiIgQm91bmRzPSIwLDAsMiwxIiBOYW1lPSJBbmFsTmV3IiBBbGlhcz0iTmV3IGFuYWx5c2lzIiBJY29uPSJKb2JOZXciIC8+DQogICAgICAgICAgICA8Q21kIElEPSIzMDA3IiBCb3VuZHM9IjAsMSwyLDEiIE5hbWU9IkFuYWxFZGl0IiBBbGlhcz0iTWFuYWdpbmciIEljb249IkpvYkVkaXQiIFZpc2libGU9IjAiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI5MTAxIiBCb3VuZHM9IjAsMSIgTmFtZT0iVmlzaWJsZUFuYWxCYXNpYyIgQWxpYXM9IkJhc2ljIGluZm8iIEljb249IklucHV0QmFzaWMiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI5MTAyIiBCb3VuZHM9IjEsMSIgTmFtZT0iVmlzaWJsZUFuYWxQVlQiIEFsaWFzPSJQVlQgaW5mbyIgSWNvbj0iSW5wdXRGbHVpZCIgLz4NCiAgICAgICAgPC9Hcm91cD4NCg0KICAgICAgICA8R3JvdXAgTmFtZT0iQW5hbHl0aWNhbCIgQWxpYXM9IkZsb3cgcGVyaW9kIGFuYWwiPg0KICAgICAgICAgICAgPENtZCBJRD0iMzAwMyIgQm91bmRzPSIwLDAsMiwxIiBOYW1lPSJBbmFsUEYiIEFsaWFzPSJQZXJpb2Qgc2VsZWN0IiBFeHRJbmZvPSJQRiIgSWNvbj0iUEYiIC8+DQogICAgICAgICAgICA8Q21kIElEPSIzMDA0IiBCb3VuZHM9IjAsMSwyLDEiIE5hbWU9IkFuYWxGbG93U2VnIiBBbGlhcz0iUGVyaW9kIGFuYWwiIEljb249IkZsb3dQZXJpb2QiIC8+DQogICAgICAgIDwvR3JvdXA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9IkFuYWx5dGljYWwiIEFsaWFzPSJJbnRlcnByZXRhdGlvbiBGaXR0aW5nIj4NCg0KICAgICAgICAgICAgPENtZCBJRD0iMzEwNSIgQm91bmRzPSIwLDAsMiwxIiBOYW1lPSJEZWNvbnZvbHYiIEFsaWFzPSJEZWNvbnZvbHV0aW9uIiBJY29uPSJEZWNvbnZvbHYiIFZpc2libGU9IjAiIC8+DQogICAgICAgICAgICA8Q21kIElEPSIzMTAxIiBCb3VuZHM9IjAsMSwyLDEiIE5hbWU9IkZpdE1vZGVsIiBBbGlhcz0iQW5hbHl0aWNhbCIgSWNvbj0iRml0TW9kZWwiIC8+DQogICAgICAgICAgICA8Q21kIElEPSIzMTA0IiBCb3VuZHM9IjAsMiwyLDEiIE5hbWU9Im5tRml0TW9kZWwiIEFsaWFzPSJOdW1lcmljYWwiIEljb249IkZpdE1vZGVsIiAvPg0KDQogICAgICAgICAgICA8Q21kIElEPSIzMTAyIiBCb3VuZHM9IjAsMywyLDEiIE5hbWU9IkF1dG9GaXQiIEFsaWFzPSJGaXR0aW5nIiBJY29uPSJBdXRvRml0IiAvPg0KICAgICAgIDwvR3JvdXA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9Ik51bWVyaWNhbCIgQWxpYXM9Ikdlb2xvZ2ljYWwgTW9kZWxpbmcoRGVidWcpIiBWaXNpYmxlPSIwIj4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjUwMDIiIEJvdW5kcz0iMCwwLDIsMSIgTmFtZT0iUHJvcGVydHlMb2FkIiBBbGlhcz0iUHJvcGVydHkgSW1wb3J0IiBJY29uPSJQcmVwYXJlR3JpZCIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjUxMDIiIEJvdW5kcz0iMCwxLDIsMSIgTmFtZT0iUnVuR3JpZCIgQWxpYXM9IkdyaWQgR2VuZXJhdGlvbiIgSWNvbj0iUGxhdGVGaXQiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI1MjAxIiBCb3VuZHM9IjAsMiwyLDEiIE5hbWU9IkFuYWxNYXAiIEFsaWFzPSJDYWxjdWxhdGlvbiIgSWNvbj0iUnVuRXgiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI1MjAyIiBCb3VuZHM9IjAsMywyLDEiIE5hbWU9IkFuYWxQRiIgQWxpYXM9IkF1eGlsaWFyeSBGaXR0aW5nIiBFeHRJbmZvPSJQRiIgSWNvbj0iUnVuT3RoZXIiIFZpc2libGU9IjAiLz4NCiAgICAgICA8L0dyb3VwPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJXZWxsTWFwIiBBbGlhcz0iV2VsbCBNYXAiPg0KICAgICAgICAgICAgPENtZCBJRD0iMzAwOCIgQm91bmRzPSIwLDAsMiwxIiBOYW1lPSJBbmFsTWFwIiBBbGlhcz0iTWFwIiBJY29uPSJNYXAyRCIgVmlzaWJsZT0iMSIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjMwMTgiIEJvdW5kcz0iMCwxLDIsMSIgTmFtZT0iQW5hbEludGVyZmVyZSIgQWxpYXM9IkludGVyZmVyZW5jZSBTZXR0aW5nIiBJY29uPSJNYXAyRCIgVmlzaWJsZT0iMCIgLz4NCiAgICAgICAgPC9Hcm91cD4NCg0KICAgICAgICA8R3JvdXAgTmFtZT0iV2luZG93IiBBbGlhcz0iV2luZG93IERpc3BsYXkoRGVidWcpIiBWaXNpYmxlPSIwIiA+DQogICAgICAgICAgICA8Q21kIElEPSI5MDAyIiBCb3VuZHM9IjAsMCIgTmFtZT0iVmlzaWJsZU1vZGVscyIgQWxpYXM9Ik1vZGVsIFdpbmRvdyIgSWNvbj0iVmlzaWJsZU1vZGVscyIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkwMDMiIEJvdW5kcz0iMSwwIiBOYW1lPSJWaXNpYmxlUGFyYW1ldGVycyIgQWxpYXM9IlBhcmFtZXRlciBXaW5kb3ciIEljb249IlZpc2libGVQYXJhbWV0ZXJzIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTEwMSIgQm91bmRzPSIwLDEiIE5hbWU9IlZpc2libGVBbmFsQmFzaWMiIEFsaWFzPSJCYXNpYyBJbmZvIiBJY29uPSJJbnB1dEJhc2ljIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTEwMiIgQm91bmRzPSIxLDEiIE5hbWU9IlZpc2libGVBbmFsUFZUIiBBbGlhcz0iUFZUIERhdGEiIEljb249IklucHV0Rmx1aWQiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI5MTAzIiBCb3VuZHM9IjAsMiIgTmFtZT0iVmlzaWJsZUFuYWxEaWZmIiBBbGlhcz0iRElGRiBEYXRhIiBJY29uPSJJbnB1dEZsdWlkIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTEwNCIgQm91bmRzPSIxLDIiIE5hbWU9IlZpc2libGVBbmFsUHNldSIgQWxpYXM9IlBzZXVkbyBQcmVzc3VyZSBEYXRhIiBJY29uPSJJbnB1dEZsdWlkIiAvPg0KICAgICAgICA8L0dyb3VwPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJIZWxwIiBBbGlhcz0iSGVscCI+DQogICAgICAgICAgICA8Q21kIElEPSIxMDAwMiIgQm91bmRzPSIwLDAsMiwxIiBOYW1lPSJIZWxwIiBBbGlhcz0iSGVscCIgSWNvbj0iSGVscCIgLz4NCiAgICAgICAgPC9Hcm91cD4NCg0KICAgIDwvVGFiPg0KDQoNCiAgICA8VGFiIElEPSIyIiBOYW1lPSJEYXRhTWFuYWdlciIgQWxpYXM9IkRhdGEgTWFuYWdlciIgPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJEYXRhTWFuYWdlciIgQWxpYXM9IldlbGwiPg0KICAgICAgICAgICAgPENtZCBJRD0iMTA5OSIgQm91bmRzPSIwLDAsMiwxIiBOYW1lPSJXZWxsTmV3IiBBbGlhcz0iTmV3IFdlbGwoVykiIEljb249IldlbGxOZXciIC8+DQogICAgICAgIDwvR3JvdXA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9IkRhdGFNYW5hZ2VyIiBBbGlhcz0iQmFzaWMgRGF0YSI+DQogICAgICAgICAgICA8Q21kIElEPSIyMDAxIiBCb3VuZHM9IjAsMCwyLDEiIE5hbWU9IkRhdGFXZWxsQmFzaWMiIEFsaWFzPSJXZWxsIEJhc2ljIERhdGEoQikiIEV4dEluZm89IkJfV0VMTCIgSWNvbj0iQmFzaWNEYXRhIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMjAwMiIgQm91bmRzPSIwLDEsMiwxIiBOYW1lPSJEYXRhTGF5ZXIiIEFsaWFzPSJHZW9sb2dpY2FsIExheWVyIERhdGEoTCkiIEV4dEluZm89IkJfTEFZRVIiIEljb249IkxheWVyRGF0YSIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjIwMDMiIEJvdW5kcz0iMCwyLDIsMSIgTmFtZT0iRGF0YVJlcyIgQWxpYXM9IlJlc2Vydm9pciBEYXRhKFIpIiBFeHRJbmZvPSJQX0RBVEFfUkVTIiBJY29uPSJSZXNEYXRhIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMjAwNCIgQm91bmRzPSIwLDMsMiwxIiBOYW1lPSJEYXRhRmx1IiBBbGlhcz0iRmx1aWQgUHJvcGVydHkgRGF0YShGKSIgRXh0SW5mbz0iUF9EQVRBX0ZMVUlEIiBJY29uPSJGbHVpZFByb3BlcnR5IiAvPg0KICAgICAgICA8L0dyb3VwPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJEYXRhTWFuYWdlciIgQWxpYXM9IlByZXNzdXJlIFJhdGUiPg0KICAgICAgICAgICAgPENtZCBJRD0iMjAwNSIgQm91bmRzPSIwLDAsMiwxIiBOYW1lPSJEYXRhUmF0ZSIgQWxpYXM9IlJhdGUgRGF0YShRKSIgRXh0SW5mbz0iUF9EQVRBX0dBVUdFX0YiIEljb249IlJhdGVEYXRhIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMjAwNiIgQm91bmRzPSIwLDEsMiwxIiBOYW1lPSJEYXRhUHJlIiBBbGlhcz0iUHJlc3N1cmUgRGF0YShQKSIgRXh0SW5mbz0iUF9EQVRBX0dBVUdFX1AiIEljb249IlByZXNzdXJlRGF0YSIgLz4NCiAgICAgICAgPC9Hcm91cD4NCg0KICAgICAgICA8R3JvdXAgTmFtZT0iR1g2IiBBbGlhcz0iUGxhdGZvcm0gSW50ZXJvcGVyYWJpbGl0eSI+DQogICAgICAgICAgICA8Q21kIElEPSIyMDA3IiBCb3VuZHM9IjAsMCwyLDEiIE5hbWU9Ikd4NkNvbm5lY3RTZXJ2ZXIiIEFsaWFzPSJHWDYgSW50ZXJvcGVyYWJpbGl0eShDKSIgSWNvbj0iR3g2Q29ubmVjdFNlcnZlciIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjIwMDgiIEJvdW5kcz0iMCwxLDIsMSIgTmFtZT0iR3g2R2V0VGFza3MiIEFsaWFzPSJHZXQgVGFza3MoRCkiIEljb249Ikd4NkdldFRhc2tzIiAgVmlzaWJsZT0iMCIvPg0KICAgICAgICAgICAgPENtZCBJRD0iMjAwOSIgQm91bmRzPSIwLDIsMiwxIiBOYW1lPSJHeDZVcGRhdGVUYXNrcyIgQWxpYXM9IlVwZGF0ZSBTdGF0dXMoVSkiIEljb249Ikd4NlVwZGF0ZVRhc2tzIiAgVmlzaWJsZT0iMCIvPg0KICAgICAgICA8L0dyb3VwPg0KDQogICAgPC9UYWI+DQoNCiAgICA8VGFiIElEPSIyMDEiIE5hbWU9IkRhdGFFZGl0IiBBbGlhcz0iRGF0YSBFZGl0IiA+DQogICAgICAgIDxHcm91cCBOYW1lPSJEYXRhRWRpdCIgQWxpYXM9IkRhdGEgRWRpdGluZyI+DQogICAgICAgICAgICA8Q21kIElEPSIzMDAxIiBCb3VuZHM9IjAsMCwyLDEiIE5hbWU9IkFuYWxGbHUiIEFsaWFzPSJSYXRlIEVkaXRpbmciIEV4dEluZm89IkYiIE1kaVR5cGU9IkRhdGFFZGl0IiBJY29uPSJSYXRlRGF0YSIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjMwMDIiIEJvdW5kcz0iMCwxLDIsMSIgTmFtZT0iQW5hbFByZXNzIiBBbGlhcz0iUHJlc3N1cmUgRWRpdGluZyIgRXh0SW5mbz0iUCIgTWRpVHlwZT0iRGF0YUVkaXQiIEljb249IlByZXNzdXJlRGF0YSIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjMzMDMiIEJvdW5kcz0iMCwyLDIsMSIgTmFtZT0iQW5hbFByZUNvbiIgQWxpYXM9IlByZXNzdXJlIENvbnZlcnNpb24iIEV4dEluZm89IlAiIE1kaVR5cGU9IkRhdGFFZGl0IiBJY29uPSJBbmFsUHJlQ29uIiAvPg0KICAgICAgICA8L0dyb3VwPg0KICAgIDwvVGFiPg0KDQogICAgPFRhYiBJRD0iMyIgTmFtZT0iQW5hbHl0aWNhbFRlc3QiIEFsaWFzPSJJbnRlcnByZXRhdGlvbiIgPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJBbmFsRWRpdCIgQWxpYXM9IkFuYWx5c2lzIE1hbmFnZW1lbnQiPg0KICAgICAgICAgICAgPENtZCBJRD0iMzAwNiIgQm91bmRzPSIwLDAiIE5hbWU9IkFuYWxOZXciIEFsaWFzPSJOZXcgQW5hbHlzaXMiIEljb249IkpvYk5ldyIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjMwMDciIEJvdW5kcz0iMSwwIiBOYW1lPSJBbmFsRWRpdCIgQWxpYXM9IkFuYWx5c2lzIE1hbmFnZW1lbnQiIEljb249IkpvYkVkaXQiIC8+DQogICAgICAgIDwvR3JvdXA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9IlNlZ0FuYWwiIEFsaWFzPSJGbG93IFBlcmlvZCBBbmFseXNpcyI+DQogICAgICAgICAgICA8Q21kIElEPSIzMDAzIiBCb3VuZHM9IjAsMCwyLDEiIE5hbWU9IkFuYWxQRiIgQWxpYXM9IkZsb3cgUGVyaW9kIFNlbGVjdGlvbiIgRXh0SW5mbz0iUEYiIEljb249IlBGIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMzAwNCIgQm91bmRzPSIwLDEsMiwxIiBOYW1lPSJBbmFsRmxvd1NlZyIgQWxpYXM9IkZsb3cgUGVyaW9kIEFuYWx5c2lzIiBJY29uPSJGbG93UGVyaW9kIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMzAwNSIgQm91bmRzPSIwLDIsMiwxIiBOYW1lPSJBbmFsT3RoZXJzIiBBbGlhcz0iQ2hhcmFjdGVyaXN0aWMgTGluZSBBbmFseXNpcyIgVHlwZT0iMSIgIFZpc2libGU9IjAiIEV4dE5hbWVzPSJDaGFydFQ7Q2hhcnRTcXJ0VDtDaGFydDI1VDtDaGFydDVUIiBFeHRJbmZvPSJDaGFydCBUO0NoYXJ0IFNxcnQoVCk7Q2hhcnQgMC4yNVQ7Q2hhcnQgLTAuNVQiIEljb249IkFzc2lzQW5hbCIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjMwMTAiIEJvdW5kcz0iMCwzLDIsMSIgTmFtZT0iQW5hbFduZE0iIEFsaWFzPSJGbG93IFBlcmlvZCBXaW5kb3ciIFR5cGU9IjEiIEljb249IkFuYWxXbmRNIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMzAwOSIgQm91bmRzPSIwLDQsMiwxIiBOYW1lPSJBbmFsRGlzdHJpIiBBbGlhcz0iRGlzdHJpYnV0aW9uIENoYXJ0IiBUeXBlPSIxIiBFeHROYW1lcz0iQ2hhcnREZW47Q2hhcnRWaXMiIEV4dEluZm89IkNvbmNlbnRyYXRpb24gRGlzdHJpYnV0aW9uO1Zpc2Nvc2l0eSBEaXN0cmlidXRpb24iIEljb249IkFuYWxEaXN0cmkiIC8+DQogICAgICAgIDwvR3JvdXA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9IkRhdGFGaXQiIEFsaWFzPSJJbnRlcnByZXRhdGlvbiBGaXR0aW5nIj4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjMxMDUiIEJvdW5kcz0iMCwwLDIsMSIgTmFtZT0iRGVjb252b2x2IiBBbGlhcz0iRGVjb252b2x1dGlvbihEZWJ1ZykiIEljb249IkRlY29udm9sdiIgLz4NCg0KICAgICAgICAgICAgPENtZCBJRD0iMzEwMSIgQm91bmRzPSIwLDEsMiwxIiBOYW1lPSJGaXRNb2RlbCIgQWxpYXM9IkFuYWx5dGljYWwgU29sdXRpb24iIEljb249IkZpdE1vZGVsIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMzEwNCIgQm91bmRzPSIwLDIsMiwxIiBOYW1lPSJubUZpdE1vZGVsIiBBbGlhcz0iTnVtZXJpY2FsIFNvbHV0aW9uIiBJY29uPSJGaXRNb2RlbCIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjMxMDIiIEJvdW5kcz0iMCwzLDIsMSIgTmFtZT0iQXV0b0ZpdCIgQWxpYXM9IkF1dG8gRml0dGluZyIgSWNvbj0iQXV0b0ZpdCIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjMxMDMiIEJvdW5kcz0iMCw0LDIsMSIgTmFtZT0iUGxhdGVGaXQiIEFsaWFzPSJTZW5zaXRpdml0eSBBbmFseXNpcyIgSWNvbj0iUGxhdGVGaXQiIC8+DQogICAgICAgPC9Hcm91cD4NCg0KICAgICAgICA8R3JvdXAgTmFtZT0iQUlUZXN0IiBBbGlhcz0iSW50ZWxsaWdlbnQgV2VsbCBUZXN0aW5nIj4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjM5MDEiIEJvdW5kcz0iMCwwLDIsMSIgTmFtZT0iTW9kZWxDbGFzc2lmeSIgQWxpYXM9Ik1vZGVsIFJlY29nbml0aW9uIiBJY29uPSJNb2RlbENsYXNzaWZ5IiAvPg0KICAgICAgICA8L0dyb3VwPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJSZWxhdGl2ZVRvb2wiIEFsaWFzPSJSZWxhdGVkIFRvb2xzIj4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjMyMDEiIEJvdW5kcz0iMCwwLDIsMSIgTmFtZT0iVGltZSIgQWxpYXM9IlRpbWUiIEljb249IlRpbWUiIC8+DQogICAgICAgICAgICA8Q21kIElEPSIzMjAyIiBCb3VuZHM9IjAsMSIgTmFtZT0iU2hvd01vZGVsQ2hhcnRzIiBBbGlhcz0iTW9kZWwgU2NoZW1hdGljIiBJY29uPSJTaG93TW9kZWxDaGFydHMiIC8+DQogICAgICAgICAgICA8Q21kIElEPSIzMjA0IiBCb3VuZHM9IjEsMSIgTmFtZT0iU2F2ZUFzTW9kZWxTa2V0Y2giIEFsaWFzPSJTYXZlIEFzIFNjaGVtYXRpYyIgSWNvbj0iU2F2ZUFzTW9kZWxTa2V0Y2giIC8+DQoNCiAgICAgICA8L0dyb3VwPg0KDQo8IS0tICAgICAgICAgICAgICAgICAgICA8Q21kIElEPSIzMjAzIiBCb3VuZHM9IjAsMSIgTmFtZT0iU2hvd01vZGVsU2tldGNoIiBBbGlhcz0iVGhlb3J5IiBJY29uPSJTaG93TW9kZWxTa2V0Y2giIC8+PEdyb3VwIE5hbWU9IlRvb2xTIiBBbGlhcz0iRXh0ZW5kZWQgRnVuY3Rpb25zIj4NCiAgICAgICAgICAgIDxDbWQgSUQ9Ijk4MDEiIEJvdW5kcz0iMCwwLDIsMSIgTmFtZT0iRmxvd1RvUyIgQWxpYXM9IlJhdGUgdG8gU2tpbiBGYWN0b3IiIEljb249IkZsb3dUb1MiIFZpc2libGU9IjAiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI5MjAxIiBCb3VuZHM9IjAsMSwyLDEiIE5hbWU9Ik1peFZpc2Nvc2l0eSIgQWxpYXM9Ik1peGVkIFZpc2Nvc2l0eSIgSWNvbj0iTWl4VmlzY29zaXR5IiBWaXNpYmxlPSIwIiAvPg0KICAgICAgIDwvR3JvdXA+LS0+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9IkpvYnMiIEFsaWFzPSJSZXN1bHQgTWFuYWdlbWVudCI+DQogICAgICAgICAgICA8Q21kIElEPSIxMDA4IiBCb3VuZHM9IjAsMCIgTmFtZT0iUnN0TG9hZCIgQWxpYXM9IkxvYWQgUmVzdWx0cyIgSWNvbj0iTG9hZEpvYnMiIC8+DQogICAgICAgICAgICA8Q21kIElEPSIxMDA5IiBCb3VuZHM9IjEsMCIgTmFtZT0iUnN0U2F2ZSIgVHlwZT0iMSIgRXh0TmFtZXM9IlJzdFNhdmVDdXI7UnN0U2F2ZUFsbCIgRXh0SW5mbz0iU2F2ZSBDdXJyZW50IFJlc3VsdDtTYXZlIEFsbCBSZXN1bHRzIiBBbGlhcz0iU2F2ZSBSZXN1bHRzIiBJY29uPSJTYXZlSm9icyIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjEwMTEiIEJvdW5kcz0iMCwxLDIsMSIgTmFtZT0iVG9OdW1lcmljYWwiIEFsaWFzPSJUby1OdW1lcmljYWwiIEljb249IkxvYWRKb2JzIiBWaXNpYmxlPSIwIiAvPg0KICAgICAgICA8L0dyb3VwPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJXaW5kb3ciIEFsaWFzPSJXaW5kb3cgRGlzcGxheSI+DQogICAgICAgICAgICA8Q21kIElEPSI5MDAyIiBCb3VuZHM9IjAsMCIgTmFtZT0iVmlzaWJsZU1vZGVscyIgQWxpYXM9Ik1vZGVsIFdpbmRvdyIgSWNvbj0iVmlzaWJsZU1vZGVscyIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkwMDMiIEJvdW5kcz0iMSwwIiBOYW1lPSJWaXNpYmxlUGFyYW1ldGVycyIgQWxpYXM9IlBhcmFtZXRlciBXaW5kb3ciIEljb249IlZpc2libGVQYXJhbWV0ZXJzIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTEwMSIgQm91bmRzPSIwLDEiIE5hbWU9IlZpc2libGVBbmFsQmFzaWMiIEFsaWFzPSJCYXNpYyBJbmZvIiBJY29uPSJJbnB1dEJhc2ljIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTEwMiIgQm91bmRzPSIxLDEiIE5hbWU9IlZpc2libGVBbmFsUFZUIiBBbGlhcz0iUFZUIERhdGEiIEljb249IklucHV0Rmx1aWQiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI5MTAzIiBCb3VuZHM9IjAsMiIgTmFtZT0iVmlzaWJsZUFuYWxEaWZmIiBBbGlhcz0iRElGRiBEYXRhIiBJY29uPSJJbnB1dEZsdWlkIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTEwNCIgQm91bmRzPSIxLDIiIE5hbWU9IlZpc2libGVBbmFsUHNldSIgQWxpYXM9IlBzZXVkbyBQcmVzc3VyZSBEYXRhIiBJY29uPSJJbnB1dEZsdWlkIiAvPg0KICAgICAgICA8L0dyb3VwPg0KICAgIDwvVGFiPg0KDQogICAgPFRhYiBJRD0iNSIgTmFtZT0iTnVtZXJpY2FsVGVzdCIgQWxpYXM9Ik1vZGVsaW5nIiA+DQogICAgICAgIDxHcm91cCBOYW1lPSJObU1hbmFnZXIiIEFsaWFzPSJBbmFseXNpcyBNYW5hZ2VtZW50IiBWaXNpYmxlPSIwIj4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjUwMDEiIEJvdW5kcz0iMCwwLDIsMSIgTmFtZT0iQW5hbE5ldyIgQWxpYXM9IlRlbXBvcmFyeSBUZXN0IDEiIEljb249IlByZXBhcmVHcmlkIiBWaXNpYmxlPSIwIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iNTAwMiIgQm91bmRzPSIwLDEsMiwxIiBOYW1lPSJQcm9wZXJ0eUxvYWQiIEFsaWFzPSJUZW1wb3JhcnkgVGVzdCAyIiBJY29uPSJQcmVwYXJlR3JpZCIgIFZpc2libGU9IjAiLz4NCiAgICAgICAgPC9Hcm91cD4NCg0KICAgICAgICA8R3JvdXAgTmFtZT0iTm1BbmFsQ2hhbmdlIiBBbGlhcz0iQW5hbHlzaXMgU3dpdGNoIj4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjUxMzAiIEJvdW5kcz0iMCwwIiBOYW1lPSJObUFuYWxDaGFuZ2UiIEFsaWFzPSJBbmFseXNpcyBTd2l0Y2giIEljb249IkpvYkVkaXQiIC8+DQogICAgICAgPC9Hcm91cD4NCg0KICAgICAgICA8R3JvdXAgTmFtZT0iTnRJbml0IiBBbGlhcz0iTW9kZWwgR2VvbWV0cmljIE9iamVjdHMiPg0KICAgICAgICAgICAgPENtZCBJRD0iNTExOCIgQm91bmRzPSIwLDAsMiwxIiBOYW1lPSJObU1hcCIgQWxpYXM9Ik1hcCIgSWNvbj0iTm1JbWFnZSIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjUxMTkiIEJvdW5kcz0iMCwxLDIsMSIgTmFtZT0iTm1VbmxvY2tlZCIgQWxpYXM9IkxvY2siIEljb249Ik5tVW5sb2NrZWQiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI1MTAyIiBCb3VuZHM9IjAsMiwyLDEiIE5hbWU9Ik5tSW1hZ2UiIEFsaWFzPSJSZXNlcnZvaXIgTWFwIiBJY29uPSJObUltYWdlIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iNTEyMCIgQm91bmRzPSIwLDMsMiwxIiBOYW1lPSJObU1lYXN1cmUiIEFsaWFzPSJTY2FsZSBCYXIiIEljb249Ik5tTWVhc3VyZSIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjUxMDMiIEJvdW5kcz0iMCw0LDIsMSIgTmFtZT0iTm1Qb2x5Z29uIiBBbGlhcz0iUG9seWdvbiBCb3VuZGFyeSIgSWNvbj0iTm1Qb2x5Z29uIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iNTEwNCIgQm91bmRzPSIwLDUiIE5hbWU9Ik5tUG9seWdvbiIgQWxpYXM9IlJlY3RhbmdsZSBCb3VuZGFyeSIgSWNvbj0iTm1SZWN0YW5nbGUiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI1MTA1IiBCb3VuZHM9IjEsNSIgTmFtZT0iTm1Qb2x5Z29uIiBBbGlhcz0iQ2lyY2xlIEJvdW5kYXJ5IiBJY29uPSJObVJvdW5kIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iNTEwNiIgQm91bmRzPSIwLDYsMiwxIiBOYW1lPSJObUZhdWx0IiBBbGlhcz0iRmF1bHQiIEljb249Ik5tRmF1bHQiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI1MTA3IiBCb3VuZHM9IjAsNyIgTmFtZT0iTm1XZWxsIiBBbGlhcz0iU2VsZWN0IFdlbGwiIEljb249Ik5tV2VsbCIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjUxMDgiIEJvdW5kcz0iMSw3IiBOYW1lPSJObVdlbGwiIEFsaWFzPSJOZXcgV2VsbCIgSWNvbj0iTm1XZWxsIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iNTEwOSIgQm91bmRzPSIwLDgsMiwxIiBOYW1lPSJObUZhdWx0IiBBbGlhcz0iRnJhY3R1cmUiIEljb249Ik5tRmF1bHQiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI1MTEwIiBCb3VuZHM9IjAsOSIgTmFtZT0iTm1MaW1pdCIgQWxpYXM9IlJlZ2lvbiIgSWNvbj0iTm1MaW1pdCIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjUxMTEiIEJvdW5kcz0iMSw5IiBOYW1lPSJObVJlZ2lvbiIgQWxpYXM9Ik1hcmsgUmVnaW9uIiBJY29uPSJObVJlZ2lvbiIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjUxMjEiIEJvdW5kcz0iMCwxMCwyLDEiIE5hbWU9Ik5tRGVsZXRlIiBBbGlhcz0iRGVsZXRlIiBJY29uPSJObURlbGV0ZSIgLz4NCiAgICAgICA8L0dyb3VwPg0KDQogICAgICAgPEdyb3VwIE5hbWU9Ik50UmVzZXJ2b2lyIiBBbGlhcz0iUmVzZXJ2b2lyIENoYXJhY3RlcmlzdGljcyI+CiAgICAgICAgICAgIDxDbWQgSUQ9IjUxMTIiIEJvdW5kcz0iMCwwLDIsMSIgTmFtZT0iTm1HZW9tZXRyeSIgQWxpYXM9IkxheWVyIERpdmlzaW9uIiBJY29uPSJObUdlb21ldHJ5IiAvPgogICAgICAgICAgICA8Q21kIElEPSI1MTEzIiBCb3VuZHM9IjAsMSwyLDEiIE5hbWU9Ik5tUHJvcGVydGllcyIgQWxpYXM9IlJlc2Vydm9pciBQcm9wZXJ0aWVzIiBJY29uPSJObVByb3BlcnRpZXMiIC8+CiAgICAgICAgICAgIDxDbWQgSUQ9IjUxMjIiIEJvdW5kcz0iMCwyLDIsMSIgTmFtZT0iTm1ERk4iIEFsaWFzPSJERk4iIEljb249Ik5tREZOIiAvPgogICAgICAgICAgICA8Q21kIElEPSI1MTI2IiBCb3VuZHM9IjAsMywyLDEiIE5hbWU9Ik5tSW50ZXJwb2xhdGlvbiIgQWxpYXM9IlByb3BlcnR5IEludGVycG9sYXRpb24iIEljb249Ik5tSW50ZXJwb2xhdGlvbiIgLz4KICAgICAgIDwvR3JvdXA+Cg0KICAgICAgIDxHcm91cCBOYW1lPSJOdE1vZGVsIiBBbGlhcz0iTW9kZWwgR2VuZXJhdGlvbiI+DQogICAgICAgICAgICAgPENtZCBJRD0iNTExNCIgQm91bmRzPSIwLDAsMiwxIiBOYW1lPSJObUdyaWQiIEFsaWFzPSJHcmlkIEdlbmVyYXRpb24iIEljb249Ik5tR3JpZCIgLz4NCiAgICAgICAgICAgICA8Q21kIElEPSI1MTE1IiBCb3VuZHM9IjAsMSwyLDEiIE5hbWU9Ik5tQ2FjdWxhdGlvbiIgQWxpYXM9IkNhbGN1bGF0aW9uIFNvbHV0aW9uIiBJY29uPSJUaW1lIiAvPg0KICAgICAgICAgICAgIDwhLS0NCiAgICAgICAgICAgICA8Q21kIElEPSI1MTE2IiBCb3VuZHM9IjAsMiwyLDEiIE5hbWU9Ik5tQmFjayIgQWxpYXM9IlBvc3QgUHJvY2Vzc2luZyIgSWNvbj0iVGltZSIgLz4NCiAgICAgICAgICAgICA8Q21kIElEPSI1MTE3IiBCb3VuZHM9IjAsMywyLDEiIE5hbWU9Ik5tUmVzdWx0IiBBbGlhcz0iUmVzdWx0IiBJY29uPSJGbG93UGVyaW9kIiAvPg0KICAgICAgICAgICAgIC0tPg0KICAgICAgIDwvR3JvdXA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9Ik50VG9vbHMiIEFsaWFzPSJUb29scyI+DQogICAgICAgICAgICA8Q21kIElEPSI1MTI3IiBCb3VuZHM9IjAsMCIgTmFtZT0iTm1HZW9SZWZlcmVuY2UiIEFsaWFzPSJNb2RlbCBSZWZlcmVuY2UgUG9pbnQgU2V0dGluZyIgSWNvbj0iTm1HZW9SZWZlcmVuY2UiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI1MTI4IiBCb3VuZHM9IjEsMCIgTmFtZT0iTm1Qb2ludGVyUG9zaXRpb24iIEFsaWFzPSJNb2RlbCBQb3NpdGlvbiBEaXNwbGF5IiBJY29uPSJObVBvaW50ZXJQb3NpdGlvbiIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjUxMjkiIEJvdW5kcz0iMCwxLDIsMSIgTmFtZT0iTm1NZWFzdXJlIiBBbGlhcz0iTW9kZWwgRGltZW5zaW9uIE1lYXN1cmVtZW50IiBJY29uPSJObU1lYXN1cmUiIC8+DQogICAgICAgPC9Hcm91cD4NCg0KICAgICAgICA8R3JvdXAgTmFtZT0iTnREaXNwbGF5IiBBbGlhcz0iRGlzcGxheSI+DQogICAgICAgICAgICA8Q21kIElEPSI1MTIzIiBCb3VuZHM9IjAsMCwyLDEiIE5hbWU9Ik5tU2hvdyIgQWxpYXM9IkRpc3BsYXkiIEljb249Ik5tU2hvdyIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjUxMjQiIEJvdW5kcz0iMCwxLDIsMSIgTmFtZT0iTm1QcmludFByZXZpZXciIEFsaWFzPSJQcmludCBQcmV2aWV3IiBJY29uPSJObVByaW50UHJldmlldyIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjUxMjUiIEJvdW5kcz0iMCwyLDIsMSIgTmFtZT0iTm1QcmludCIgQWxpYXM9IlByaW50IiBJY29uPSJObVByaW50IiAvPg0KICAgICAgIDwvR3JvdXA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9IldpbmRvdyIgQWxpYXM9IldpbmRvdyBEaXNwbGF5IiAgVmlzaWJsZT0iMCI+DQogICAgICAgICAgICA8Q21kIElEPSI5MDAyIiBCb3VuZHM9IjAsMCIgTmFtZT0iVmlzaWJsZU1vZGVscyIgQWxpYXM9Ik1vZGVsIFdpbmRvdyIgSWNvbj0iVmlzaWJsZU1vZGVscyIgIFZpc2libGU9IjAiLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkwMDMiIEJvdW5kcz0iMSwwIiBOYW1lPSJWaXNpYmxlUGFyYW1ldGVycyIgQWxpYXM9IlBhcmFtZXRlciBXaW5kb3ciIEljb249IlZpc2libGVQYXJhbWV0ZXJzIiAgVmlzaWJsZT0iMCIvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTEwMSIgQm91bmRzPSIwLDEiIE5hbWU9IlZpc2libGVBbmFsQmFzaWMiIEFsaWFzPSJCYXNpYyBJbmZvIiBJY29uPSJJbnB1dEJhc2ljIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTEwMiIgQm91bmRzPSIxLDEiIE5hbWU9IlZpc2libGVBbmFsUFZUIiBBbGlhcz0iUFZUIERhdGEiIEljb249IklucHV0Rmx1aWQiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI5MTAzIiBCb3VuZHM9IjAsMiIgTmFtZT0iVmlzaWJsZUFuYWxEaWZmIiBBbGlhcz0iRElGRiBEYXRhIiBJY29uPSJJbnB1dEZsdWlkIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTEwNCIgQm91bmRzPSIxLDIiIE5hbWU9IlZpc2libGVBbmFsUHNldSIgQWxpYXM9IlBzZXVkbyBQcmVzc3VyZSBEYXRhIiBJY29uPSJJbnB1dEZsdWlkIiAvPg0KICAgICAgICA8L0dyb3VwPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJObURlYnVnIiBBbGlhcz0iRnJhbWV3b3JrIFRlc3QoRGVidWcpIj4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjU5OTkiIEJvdW5kcz0iMCwwLDIsMSIgTmFtZT0iTm1EZWJ1ZyIgQWxpYXM9IkZyYW1ld29yayBDb2RlIERlYnVnZ2luZyIgSWNvbj0iUHJlcGFyZUdyaWQiIC8+DQogICAgICAgIDwvR3JvdXA+DQoNCg0KICAgIDwvVGFiPg0KDQogICAgPFRhYiBJRD0iNCIgTmFtZT0iTWluaUZyYWMiIEFsaWFzPSJNaW5pIEZyYWN0dXJpbmcoRGVidWcpIiA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9IkFuYWxFZGl0IiBBbGlhcz0iQW5hbHlzaXMgTWFuYWdlbWVudCI+DQogICAgICAgICAgICA8Q21kIElEPSIzMDA2IiBCb3VuZHM9IjAsMCIgTmFtZT0iQW5hbE5ldyIgQWxpYXM9Ik5ldyBBbmFseXNpcyIgSWNvbj0iSm9iTmV3IiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMzAwNyIgQm91bmRzPSIxLDAiIE5hbWU9IkFuYWxFZGl0IiBBbGlhcz0iQW5hbHlzaXMgTWFuYWdlbWVudCIgSWNvbj0iSm9iRWRpdCIgLz4NCiAgICAgICAgPC9Hcm91cD4NCg0KICAgICAgICA8R3JvdXAgTmFtZT0iUEEiIEFsaWFzPSJQcmVzc3VyZSBEcm9wIEFuYWx5c2lzIj4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjQwMDIiIEJvdW5kcz0iMCwwLDMsMSIgTmFtZT0iTWluaUZyQW5hbFBBIiBBbGlhcz0iUHJlc3N1cmUgRHJvcCBQcmVwYXJhdGlvbiIgRXh0SW5mbz0iUEYiIEljb249IlBGIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iNDAwMyIgQm91bmRzPSIwLDEsMywxIiBOYW1lPSJNaW5pRnJQQSIgQWxpYXM9IlByZXNzdXJlIERyb3AgQW5hbHlzaXMiIEljb249IkZsb3dQZXJpb2QiIC8+DQoNCiAgICAgICAgICAgIDxDbWQgSUQ9IjQwMDQiIEJvdW5kcz0iMCwyLDMsMSIgTmFtZT0iQ2FsU3VkZGVuU3RvcFAiIEFsaWFzPSJJbnN0YW50YW5lb3VzIFNodXQtaW4gUHJlc3N1cmUiIEljb249IlJ1bkV4IiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iNDAwNSIgQm91bmRzPSIwLDMiIE5hbWU9IkNhbEdGdW5jdGlvbiIgQWxpYXM9IkcgRnVuY3Rpb24iIEljb249IlJ1bk90aGVyIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iNDAwNiIgQm91bmRzPSIxLDMiIE5hbWU9IkNhbFNxcnRUIiBBbGlhcz0iU3F1YXJlIFJvb3Qgb2YgVGltZSIgSWNvbj0iUnVuT3RoZXIiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI0MDA3IiBCb3VuZHM9IjIsMyIgTmFtZT0iQ2FsTG9nTG9nIiBBbGlhcz0iTG9nLUxvZyBQbG90IiBJY29uPSJSdW5PdGhlciIgLz4NCiAgICAgICAgPC9Hcm91cD4NCg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJGQSIgQWxpYXM9IkZsb3cgUmF0ZSBBbmFseXNpcyI+DQogICAgICAgICAgICA8Q21kIElEPSI0MTAyIiBCb3VuZHM9IjAsMCwyLDEiIE5hbWU9Ik1pbmlGckFuYWxGQSIgQWxpYXM9IkZsb3cgUmF0ZSBQcmVwYXJhdGlvbiIgRXh0SW5mbz0iSVBSIiBJY29uPSJNaW5pRnJBbmFsRkEiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI0MTAzIiBCb3VuZHM9IjAsMSIgTmFtZT0iTWluaUZyRkFVcCIgQWxpYXM9IlN0ZXAgVXAiIEljb249IlN0ZXBVcCIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjQxMDQiIEJvdW5kcz0iMSwxIiBOYW1lPSJNaW5pRnJGQURvd24iIEFsaWFzPSJTdGVwIERvd24iIEljb249IlN0ZXBEb3duIiAvPg0KICAgICAgIDwvR3JvdXA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9IkpvYnMiIEFsaWFzPSJSZXN1bHQgTWFuYWdlbWVudCIgIFZpc2libGU9IjAiPg0KICAgICAgICAgICAgPENtZCBJRD0iMTAwOCIgQm91bmRzPSIwLDAiIE5hbWU9IlJzdExvYWQiIEFsaWFzPSJMb2FkIFJlc3VsdHMiIEljb249IkxvYWRKb2JzIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMTAwOSIgQm91bmRzPSIxLDAiIE5hbWU9IlJzdFNhdmUiIFR5cGU9IjEiIEV4dE5hbWVzPSJSc3RTYXZlQ3VyO1JzdFNhdmVBbGwiIEV4dEluZm89IlNhdmUgQ3VycmVudCBSZXN1bHQ7U2F2ZSBBbGwgUmVzdWx0cyIgQWxpYXM9IlNhdmUgUmVzdWx0cyIgSWNvbj0iU2F2ZUpvYnMiIC8+DQogICAgICAgIDwvR3JvdXA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9IldpbmRvdyIgQWxpYXM9IldpbmRvdyBEaXNwbGF5IiAgVmlzaWJsZT0iMCI+DQogICAgICAgICAgICA8Q21kIElEPSI5MDAyIiBCb3VuZHM9IjAsMCIgTmFtZT0iVmlzaWJsZU1vZGVscyIgQWxpYXM9Ik1vZGVsIFdpbmRvdyIgSWNvbj0iVmlzaWJsZU1vZGVscyIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkwMDMiIEJvdW5kcz0iMSwwIiBOYW1lPSJWaXNpYmxlUGFyYW1ldGVycyIgQWxpYXM9IlBhcmFtZXRlciBXaW5kb3ciIEljb249IlZpc2libGVQYXJhbWV0ZXJzIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTEwMSIgQm91bmRzPSIwLDEiIE5hbWU9IlZpc2libGVBbmFsQmFzaWMiIEFsaWFzPSJCYXNpYyBJbmZvIiBJY29uPSJJbnB1dEJhc2ljIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTEwMiIgQm91bmRzPSIxLDEiIE5hbWU9IlZpc2libGVBbmFsUFZUIiBBbGlhcz0iUFZUIERhdGEiIEljb249IklucHV0Rmx1aWQiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI5MTAzIiBCb3VuZHM9IjAsMiIgTmFtZT0iVmlzaWJsZUFuYWxEaWZmIiBBbGlhcz0iRElGRiBEYXRhIiBJY29uPSJJbnB1dEZsdWlkIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTEwNCIgQm91bmRzPSIxLDIiIE5hbWU9IlZpc2libGVBbmFsUHNldSIgQWxpYXM9IlBzZXVkbyBQcmVzc3VyZSBEYXRhIiBJY29uPSJJbnB1dEZsdWlkIiAvPg0KICAgICAgICA8L0dyb3VwPg0KDQogICAgPC9UYWI+DQoNCiAgICA8VGFiIElEPSI0MDEiIE5hbWU9IklQUiIgQWxpYXM9IldlbGwgUHJvZCBUZXN0IiA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9IkFuYWxFZGl0IiBBbGlhcz0iQW5hbHlzaXMgTWFuYWdlbWVudCI+DQogICAgICAgICAgICA8Q21kIElEPSIzMDA2IiBCb3VuZHM9IjAsMCIgTmFtZT0iQW5hbE5ldyIgQWxpYXM9Ik5ldyBBbmFseXNpcyIgSWNvbj0iSm9iTmV3IiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMzAwNyIgQm91bmRzPSIxLDAiIE5hbWU9IkFuYWxFZGl0IiBBbGlhcz0iQW5hbHlzaXMgTWFuYWdlbWVudCIgSWNvbj0iSm9iRWRpdCIgLz4NCiAgICAgICAgPC9Hcm91cD4NCg0KICAgICAgICA8R3JvdXAgTmFtZT0iSVBSIiBBbGlhcz0iSVBSIFByZXZpb3VzIFJlZmVyZW5jZShEZWJ1ZykiPg0KICAgICAgICAgICAgPENtZCBJRD0iNjAwMiIgQm91bmRzPSIwLDAsMiwxIiBOYW1lPSJJUFJBbmFsIiBBbGlhcz0iSVBSIFByZXBhcmF0aW9uIiBFeHRJbmZvPSJJUFIiIEljb249IklQUkFuYWwiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI2MDAzIiBCb3VuZHM9IjAsMSwyLDEiIE5hbWU9IklQUkNhbCIgQWxpYXM9IklQUiBDYWxjdWxhdGlvbiIgSWNvbj0iSVBSQ2FsIiAvPg0KICAgICAgICA8L0dyb3VwPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJXZHREYXRhUHJlcHJvY2VzcyIgQWxpYXM9IkRhdGEgUHJlcHJvY2Vzc2luZyIgVmlzaWJsZT0iMCI+DQogICAgICAgICAgICA8Q21kIElEPSI2MTAxIiBCb3VuZHM9IjAsMCwyLDEiIE5hbWU9IldkdERhdGFBc3NuIiBBbGlhcz0iRGF0YSBOb3JtYWxpemF0aW9uIiBFeHRJbmZvPSJJUFIiIEljb249IklQUkFuYWwiICBWaXNpYmxlPSIwIi8+DQogICAgICAgICAgICA8Q21kIElEPSI2MTAyIiBCb3VuZHM9IjAsMSwyLDEiIE5hbWU9IldkdE90aGVyIiBBbGlhcz0iT3RoZXJzIiBJY29uPSJXZHRPdGhlciIgVmlzaWJsZT0iMCIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjYxMDMiIEJvdW5kcz0iMCwzLDIsMSIgTmFtZT0iV2R0V01GIiBBbGlhcz0iV2VsbGJvcmUgTXVsdGlwaGFzZSBGbG93IiBJY29uPSJXZHRXTUYiICBWaXNpYmxlPSIwIi8+DQogICAgICAgICAgICA8Q21kIElEPSI2MTA0IiBCb3VuZHM9IjAsNCwyLDEiIE5hbWU9IldkdENob2tlIiBBbGlhcz0iQ2hva2UgRmxvdyIgSWNvbj0iV2R0Q2hva2UiICBWaXNpYmxlPSIwIi8+DQogICAgICAgIDwvR3JvdXA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9IklQUiIgQWxpYXM9IlByb2R1Y3Rpdml0eSBBbmFseXNpcyI+DQogICAgICAgICAgICA8Q21kIElEPSI2MjAxIiBCb3VuZHM9IjAsMCwyLDEiIE5hbWU9IldkdElQUkNhbCIgQWxpYXM9IlJlc2Vydm9pciBQcm9kdWN0aXZpdHkgQ2FsY3VsYXRpb24iIEljb249IklQUkNhbCIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjYyMDIiIEJvdW5kcz0iMCwxLDIsMSIgTmFtZT0iV2VsbFBkdHkiIEFsaWFzPSJJbnRlZ3JhdGVkIFByb2R1Y3Rpdml0eSIgSWNvbj0iV2VsbFBkdHkiICBWaXNpYmxlPSIwIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iNjIwMyIgQm91bmRzPSIwLDIsMiwxIiBOYW1lPSJXZHRJUFJFeHQiIEFsaWFzPSJQcm9kdWN0aXZpdHkgV2VsbCBUZXN0W0V4dGVuZGVkXSIgSWNvbj0iSVBSRXh0Ii8+DQogICAgICAgICAgICA8Q21kIElEPSI2MjA0IiBCb3VuZHM9IjAsMywyLDEiIE5hbWU9IldkdElQUkFuYWwiIEFsaWFzPSJSZXNlcnZvaXIgUHJvZHVjdGl2aXR5IEFuYWx5c2lzIiBJY29uPSJJUFJBbmFsIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iNjIwNSIgQm91bmRzPSIwLDQsMiwxIiBOYW1lPSJXZWxsSW50ZWdBbmFsIiBBbGlhcz0iQ29tcHJlaGVuc2l2ZSBBbmFseXNpcyIgSWNvbj0iV2VsbEludGVnQW5hbCIgVmlzaWJsZT0iMCIgLz4NCiAgICAgICAgPC9Hcm91cD4NCg0KICAgICAgICA8R3JvdXAgTmFtZT0iSVBSIiBBbGlhcz0iUHJvZHVjdGl2aXR5IENhbGN1bGF0aW9uIj4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjYzMDEiIEJvdW5kcz0iMCwwLDIsMSIgTmFtZT0iV2R0Q2FsIiBBbGlhcz0iQ2FsY3VsYXRpb24iIEljb249IlJ1bkV4IiAvPg0KICAgICAgICA8L0dyb3VwPg0KDQoNCiAgICAgICAgPEdyb3VwIE5hbWU9IkpvYnMiIEFsaWFzPSJSZXN1bHQgTWFuYWdlbWVudCI+DQogICAgICAgICAgICA8Q21kIElEPSIxMDA4IiBCb3VuZHM9IjAsMCIgTmFtZT0iUnN0TG9hZCIgQWxpYXM9IkxvYWQgUmVzdWx0cyIgSWNvbj0iTG9hZEpvYnMiIC8+DQogICAgICAgICAgICA8Q21kIElEPSIxMDA5IiBCb3VuZHM9IjEsMCIgTmFtZT0iUnN0U2F2ZSIgVHlwZT0iMSIgRXh0TmFtZXM9IlJzdFNhdmVDdXI7UnN0U2F2ZUFsbCIgRXh0SW5mbz0iU2F2ZSBDdXJyZW50IFJlc3VsdDtTYXZlIEFsbCBSZXN1bHRzIiBBbGlhcz0iU2F2ZSBSZXN1bHRzIiBJY29uPSJTYXZlSm9icyIgLz4NCiAgICAgICAgPC9Hcm91cD4NCg0KICAgICAgICA8R3JvdXAgTmFtZT0iV2luZG93IiBBbGlhcz0iV2luZG93IERpc3BsYXkiPg0KICAgICAgICAgICAgPENtZCBJRD0iOTAwMiIgQm91bmRzPSIwLDAiIE5hbWU9IlZpc2libGVNb2RlbHMiIEFsaWFzPSJNb2RlbCBXaW5kb3ciIEljb249IlZpc2libGVNb2RlbHMiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI5MDAzIiBCb3VuZHM9IjEsMCIgTmFtZT0iVmlzaWJsZVBhcmFtZXRlcnMiIEFsaWFzPSJQYXJhbWV0ZXIgV2luZG93IiBJY29uPSJWaXNpYmxlUGFyYW1ldGVycyIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkxMDEiIEJvdW5kcz0iMCwxIiBOYW1lPSJWaXNpYmxlQW5hbEJhc2ljIiBBbGlhcz0iQmFzaWMgSW5mbyIgSWNvbj0iSW5wdXRCYXNpYyIgICBWaXNpYmxlPSIwIi8+DQogICAgICAgICAgICA8Q21kIElEPSI5MTAyIiBCb3VuZHM9IjAsMSIgTmFtZT0iVmlzaWJsZUFuYWxQVlQiIEFsaWFzPSJQVlQgRGF0YSIgSWNvbj0iSW5wdXRGbHVpZCIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkxMDMiIEJvdW5kcz0iMCwyIiBOYW1lPSJWaXNpYmxlQW5hbERpZmYiIEFsaWFzPSJESUZGIERhdGEiIEljb249IklucHV0Rmx1aWQiICAgVmlzaWJsZT0iMCIvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTEwNCIgQm91bmRzPSIxLDEiIE5hbWU9IlZpc2libGVBbmFsUHNldSIgQWxpYXM9IlBzZXVkbyBQcmVzc3VyZSBEYXRhIiBJY29uPSJJbnB1dEZsdWlkIiAvPg0KICAgICAgICA8L0dyb3VwPg0KDQoNCiAgICA8L1RhYj4NCg0KICAgIDxUYWIgSUQ9IjYiIE5hbWU9IkFkdmFuY2VkRnVuY3Rpb24iIEFsaWFzPSJBZHZhbmNlZCIgPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJEZXNpZ24iIEFsaWFzPSJXZWxsIFRlc3QgRGVzaWduIj4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjYwMDEiIEJvdW5kcz0iMCwwLDIsMSIgTmFtZT0iVGVzdERlc2lnbiIgQWxpYXM9IldlbGwgVGVzdCBEZXNpZ24iIEljb249IlRlc3REZXNpZ24iIEV4dEluZm89IlBGIiAgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjMwMDQiIEJvdW5kcz0iMCwxLDIsMSIgTmFtZT0iQW5hbEZsb3dTZWciIEFsaWFzPSJGbG93IFBlcmlvZCBBbmFseXNpcyIgSWNvbj0iRmxvd1BlcmlvZCIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjMwMDUiIEJvdW5kcz0iMCwyLDIsMSIgTmFtZT0iQW5hbE90aGVycyIgQWxpYXM9IkNoYXJhY3RlcmlzdGljIFNlZ21lbnQgQW5hbHlzaXMiIFR5cGU9IjEiIEV4dE5hbWVzPSJDaGFydFQ7Q2hhcnRTcXJ0VDtDaGFydDI1VDtDaGFydDVUIiBFeHRJbmZvPSJDaGFydCBUO0NoYXJ0IFNxcnQoVCk7Q2hhcnQgMC4yNVQ7Q2hhcnQgLTAuNVQiIEljb249IkFzc2lzQW5hbCIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjMwMDkiIEJvdW5kcz0iMCwzLDIsMSIgTmFtZT0iQW5hbERpc3RyaSIgQWxpYXM9IkRpc3RyaWJ1dGlvbiBDaGFydCIgVHlwZT0iMSIgRXh0TmFtZXM9IkNoYXJ0RGVuO0NoYXJ0VmlzIiBFeHRJbmZvPSJDb25jZW50cmF0aW9uIERpc3RyaWJ1dGlvbjtWaXNjb3NpdHkgRGlzdHJpYnV0aW9uIiBJY29uPSJBbmFsRGlzdHJpIiAvPg0KDQogICAgICAgIDwvR3JvdXA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9IkRhdGFGaXQiIEFsaWFzPSJJbnRlcnByZXRhdGlvbiBGaXR0aW5nIj4NCg0KICAgICAgICAgICAgPENtZCBJRD0iMzEwNSIgQm91bmRzPSIwLDAsMiwxIiBOYW1lPSJEZWNvbnZvbHYiIEFsaWFzPSJEZWNvbnZvbHV0aW9uIiBJY29uPSJEZWNvbnZvbHYiIFZpc2libGU9IjAiLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjMxMDEiIEJvdW5kcz0iMCwxLDIsMSIgTmFtZT0iRml0TW9kZWwiIEFsaWFzPSJBbmFseXRpY2FsIFNvbHV0aW9uIiBJY29uPSJGaXRNb2RlbCIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjMxMDQiIEJvdW5kcz0iMCwyLDIsMSIgTmFtZT0ibm1GaXRNb2RlbCIgQWxpYXM9Ik51bWVyaWNhbCBTb2x1dGlvbiIgSWNvbj0iRml0TW9kZWwiIC8+DQogICAgICAgICAgICA8Q21kIElEPSIzMTAyIiBCb3VuZHM9IjAsMywyLDEiIE5hbWU9IkF1dG9GaXQiIEFsaWFzPSJBdXRvIEZpdHRpbmciIEljb249IkF1dG9GaXQiIC8+DQogICAgICAgICAgICA8Q21kIElEPSIzMTAzIiBCb3VuZHM9IjAsNCwyLDEiIE5hbWU9IlBsYXRlRml0IiBBbGlhcz0iU2Vuc2l0aXZpdHkgQW5hbHlzaXMiIEljb249IlBsYXRlRml0IiAvPg0KICAgICAgIDwvR3JvdXA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9IkFJVGVzdCIgQWxpYXM9IkludGVsbGlnZW50IFdlbGwgVGVzdChEZWJ1ZykiPg0KICAgICAgICAgICAgPENtZCBJRD0iMzkwMSIgQm91bmRzPSIwLDAsMiwxIiBOYW1lPSJNb2RlbENsYXNzaWZ5IiBBbGlhcz0iTW9kZWwgUmVjb2duaXRpb24iIEljb249Ik1vZGVsQ2xhc3NpZnkiIC8+DQogICAgICAgIDwvR3JvdXA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9IlJlbGF0aXZlVG9vbCIgQWxpYXM9IlJlbGF0ZWQgVG9vbHMiIFZpc2libGU9IjAiPg0KICAgICAgICAgICAgPENtZCBJRD0iMzIwMSIgQm91bmRzPSIwLDAiIE5hbWU9IlRpbWUiIEFsaWFzPSJUaW1lIiBJY29uPSJUaW1lIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMzIwMiIgQm91bmRzPSIxLDAiIE5hbWU9IlNob3dNb2RlbENoYXJ0cyIgQWxpYXM9Ik1vZGVsIiBJY29uPSJTaG93TW9kZWxDaGFydHMiIC8+DQogICAgICAgICAgICA8Q21kIElEPSIzMjAzIiBCb3VuZHM9IjAsMSIgTmFtZT0iU2hvd01vZGVsU2tldGNoIiBBbGlhcz0iVGhlb3J5IiBJY29uPSJTaG93TW9kZWxTa2V0Y2giIC8+DQogICAgICAgICAgICA8Q21kIElEPSIzMjA0IiBCb3VuZHM9IjEsMSIgTmFtZT0iU2F2ZUFzTW9kZWxTa2V0Y2giIEFsaWFzPSJTYXZlIEFzIFNjaGVtYXRpYyIgSWNvbj0iU2F2ZUFzTW9kZWxTa2V0Y2giIC8+DQogICAgICAgPC9Hcm91cD4NCg0KICAgICAgICA8R3JvdXAgTmFtZT0iVG9vbFMiIEFsaWFzPSJFeHRlbmRlZCBGdW5jdGlvbnMiICBWaXNpYmxlPSIwIj4NCiAgICAgICAgICAgIDxDbWQgSUQ9Ijk4MDEiIEJvdW5kcz0iMCwwLDIsMSIgTmFtZT0iRmxvd1RvUyIgQWxpYXM9IlJhdGUgdG8gU2tpbiBGYWN0b3IiIEljb249IkZsb3dUb1MiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI5MjAxIiBCb3VuZHM9IjAsMSwyLDEiIE5hbWU9Ik1peFZpc2Nvc2l0eSIgQWxpYXM9Ik1peGVkIFZpc2Nvc2l0eSIgSWNvbj0iTWl4VmlzY29zaXR5IiAvPg0KICAgICAgIDwvR3JvdXA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9IkpvYnMiIEFsaWFzPSJSZXN1bHQgTWFuYWdlbWVudCIgVmlzaWJsZT0iMCI+DQogICAgICAgICAgICA8Q21kIElEPSIxMDA4IiBCb3VuZHM9IjAsMCIgTmFtZT0iUnN0TG9hZCIgQWxpYXM9IkxvYWQgUmVzdWx0cyIgSWNvbj0iTG9hZEpvYnMiIC8+DQogICAgICAgICAgICA8Q21kIElEPSIxMDA5IiBCb3VuZHM9IjEsMCIgTmFtZT0iUnN0U2F2ZSIgVHlwZT0iMSIgRXh0TmFtZXM9IlJzdFNhdmVDdXI7UnN0U2F2ZUFsbCIgRXh0SW5mbz0iU2F2ZSBDdXJyZW50IFJlc3VsdDtTYXZlIEFsbCBSZXN1bHRzIiBBbGlhcz0iU2F2ZSBSZXN1bHRzIiBJY29uPSJTYXZlSm9icyIgLz4NCiAgICAgICAgPC9Hcm91cD4NCg0KICAgICAgICA8R3JvdXAgTmFtZT0iV2luZG93IiBBbGlhcz0iV2luZG93IERpc3BsYXkiIFZpc2libGU9IjAiPg0KICAgICAgICAgICAgPENtZCBJRD0iOTAwMiIgQm91bmRzPSIwLDAiIE5hbWU9IlZpc2libGVNb2RlbHMiIEFsaWFzPSJNb2RlbCBXaW5kb3ciIEljb249IlZpc2libGVNb2RlbHMiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI5MDAzIiBCb3VuZHM9IjEsMCIgTmFtZT0iVmlzaWJsZVBhcmFtZXRlcnMiIEFsaWFzPSJQYXJhbWV0ZXIgV2luZG93IiBJY29uPSJWaXNpYmxlUGFyYW1ldGVycyIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkxMDEiIEJvdW5kcz0iMCwxIiBOYW1lPSJWaXNpYmxlQW5hbEJhc2ljIiBBbGlhcz0iQmFzaWMgSW5mbyIgSWNvbj0iSW5wdXRCYXNpYyIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkxMDIiIEJvdW5kcz0iMSwxIiBOYW1lPSJWaXNpYmxlQW5hbFBWVCIgQWxpYXM9IlBWVCBEYXRhIiBJY29uPSJJbnB1dEZsdWlkIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTEwMyIgQm91bmRzPSIwLDIiIE5hbWU9IlZpc2libGVBbmFsRGlmZiIgQWxpYXM9IkRJRkYgRGF0YSIgSWNvbj0iSW5wdXRGbHVpZCIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkxMDQiIEJvdW5kcz0iMSwyIiBOYW1lPSJWaXNpYmxlQW5hbFBzZXUiIEFsaWFzPSJQc2V1ZG8gUHJlc3N1cmUgRGF0YSIgSWNvbj0iSW5wdXRGbHVpZCIgLz4NCiAgICAgICAgPC9Hcm91cD4NCg0KICAgIDwvVGFiPg0KDQogICAgPFRhYiBJRD0iNyIgTmFtZT0iU3lzVG9vbCIgQWxpYXM9IlN5c3RlbSBDb25maWd1cmF0aW9uIFRvb2xzKFQpIiBWaXNpYmxlPSIwIiA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9IlN5c1Rvb2wiIEFsaWFzPSJDb25maWd1cmF0aW9uIFRvb2xzIj4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjcwMDEiIEJvdW5kcz0iMCwxLDIsMSIgTmFtZT0iU3lzVG9vbHMiIEFsaWFzPSJTeXN0ZW0gQ29uZmlndXJhdGlvbiBUb29scyIgSWNvbj0iU3lzVG9vbHMiICAvPg0KICAgICAgICA8L0dyb3VwPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJNb2RlbE1hbmFnZXIiIEFsaWFzPSJNb2RlbCBNYW5hZ2VtZW50Ij4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjcwMDIiIEJvdW5kcz0iMCwwLDIsMSIgTmFtZT0iTW9kZWxTY2FuIiBBbGlhcz0iTW9kZWwgVmlldyIgSWNvbj0iTW9kZWxTY2FuIiAvPg0KICAgICAgICA8L0dyb3VwPg0KDQogICAgPC9UYWI+DQoNCiAgICA8VGFiIElEPSI4IiBOYW1lPSJSZXN1bHQiIEFsaWFzPSJSZXN1bHRzIiA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9IkpvYnMiIEFsaWFzPSJSZXN1bHQgTWFuYWdlbWVudCI+DQogICAgICAgICAgICA8Q21kIElEPSIxMDA4IiBCb3VuZHM9IjAsMCIgTmFtZT0iUnN0TG9hZCIgQWxpYXM9IkxvYWQgUmVzdWx0cyIgSWNvbj0iTG9hZEpvYnMiIC8+DQogICAgICAgICAgICA8Q21kIElEPSIxMDA5IiBCb3VuZHM9IjEsMCIgTmFtZT0iUnN0U2F2ZSIgVHlwZT0iMSIgRXh0TmFtZXM9IlJzdFNhdmVDdXI7UnN0U2F2ZUFsbCIgRXh0SW5mbz0iU2F2ZSBDdXJyZW50IFJlc3VsdDtTYXZlIEFsbCBSZXN1bHRzIiBBbGlhcz0iU2F2ZSBSZXN1bHRzIiBJY29uPSJTYXZlSm9icyIgLz4NCiAgICAgICAgPC9Hcm91cD4NCg0KICAgICAgICA8R3JvdXAgTmFtZT0iUmVzQ29tcGFyZSIgQWxpYXM9IlJlc3VsdCBDb21wYXJpc29uIj4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjgwMDMiIEJvdW5kcz0iMCwwLDIsMSIgTmFtZT0iUmVzQ29tcGFyZSIgQWxpYXM9IlJlc3VsdCBDb21wYXJpc29uIiBJY29uPSJSZXNDb21wYXJlIiAgLz4NCiAgICAgICAgPC9Hcm91cD4NCg0KICAgICAgICA8R3JvdXAgTmFtZT0iUHJpbnQiIEFsaWFzPSJSZXBvcnQgUHJpbnRpbmciPg0KICAgICAgICAgICAgPENtZCBJRD0iODAwMSIgQm91bmRzPSIwLDAiIE5hbWU9IlJlcG9ydENvbmZpZyIgQWxpYXM9IlJlcG9ydCBTZXR0aW5ncyIgSWNvbj0icmVwb3J0Q29uZmlnIiAgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjgwMDQiIEJvdW5kcz0iMSwwIiBOYW1lPSJQcmludFByZXZpZXciIEFsaWFzPSJSZXBvcnQgUHJldmlldyIgSWNvbj0iUHJlUHJpbnQiICAvPg0KICAgICAgICAgICAgPENtZCBJRD0iODAwMiIgQm91bmRzPSIwLDEiIE5hbWU9IlByaW50IiBBbGlhcz0iUHJpbnQoSW5jbHVkZSBQREYpIiBJY29uPSJQcmludCIgIC8+DQogICAgICAgICAgICA8Q21kIElEPSI4MDA1IiBCb3VuZHM9IjEsMSIgTmFtZT0iRXhwb3J0V29yZCIgQWxpYXM9IkV4cG9ydChXb3JkKSIgSWNvbj0iV29yZDE2IiAgLz4NCiAgICAgICAgPC9Hcm91cD4NCg0KICAgICAgICA8R3JvdXAgTmFtZT0iV2luZG93IiBBbGlhcz0iV2luZG93IERpc3BsYXkiIFZpc2libGU9IjAiPg0KICAgICAgICAgICAgPENtZCBJRD0iOTAwMyIgQm91bmRzPSIwLDAsMiwxIiBOYW1lPSJWaXNpYmxlUGFyYW1ldGVycyIgQWxpYXM9IlBhcmFtZXRlciBXaW5kb3ciIEljb249IlZpc2libGVQYXJhbWV0ZXJzIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTAwNCIgQm91bmRzPSIwLDEsMiwxIiBOYW1lPSJWaXNpYmxlUHR5cyIgQWxpYXM9IlByb3BlcnR5IFdpbmRvdyIgSWNvbj0iUHJvcGVydHlXaW5kb3ciIC8+DQoNCiAgICAgICAgPC9Hcm91cD4NCg0KICAgIDwvVGFiPg0KDQogICAgPFRhYiBJRD0iOSIgTmFtZT0iV2luZG93IiBBbGlhcz0iV2luZG93IiA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9IldpbmRvdyIgQWxpYXM9IkJhc2ljIj4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkwMDEiIEJvdW5kcz0iMCwwLDIsMSIgTmFtZT0iVmlzaWJsZVByb2pUcmVlRGEiIEFsaWFzPSJQcm9qZWN0IFRyZWUiIEljb249IlByb2pUcmVlIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTAwOCIgQm91bmRzPSIwLDEsMiwxIiBOYW1lPSJWaXNpYmxlUHJvalRyZWVKYiIgQWxpYXM9IkFuYWx5c2lzIFRyZWUiIEljb249IlByb2pUcmVlIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTAwOSIgQm91bmRzPSIwLDIsMiwxIiBOYW1lPSJWaXNpYmxlUHJvalRyZWVScyIgQWxpYXM9IlJlc3VsdCBUcmVlIiBJY29uPSJQcm9qVHJlZSIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkwMDIiIEJvdW5kcz0iMCwzIiBOYW1lPSJWaXNpYmxlTW9kZWxzIiBBbGlhcz0iTW9kZWwgV2luZG93IiBJY29uPSJWaXNpYmxlTW9kZWxzIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTAwMyIgQm91bmRzPSIxLDMiIE5hbWU9IlZpc2libGVQYXJhbWV0ZXJzIiBBbGlhcz0iUGFyYW1ldGVyIFdpbmRvdyIgSWNvbj0iVmlzaWJsZVBhcmFtZXRlcnMiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI5MDA0IiBCb3VuZHM9IjAsNCIgTmFtZT0iVmlzaWJsZVB0eXMiIEFsaWFzPSJQcm9wZXJ0eSBXaW5kb3ciIEljb249IlByb3BlcnR5V2luZG93IiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTAwNSIgQm91bmRzPSIxLDQiIE5hbWU9IlZpc2libGVMb2dzIiBBbGlhcz0iTG9nIFdpbmRvdyIgSWNvbj0iVmlzaWJsZUxvZ3MiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI5MDA2IiBCb3VuZHM9IjAsNSIgTmFtZT0iU3RhY2tlZFByb2plY3QiIEFsaWFzPSJQcm9qZWN0IFdpbmRvdyIgSWNvbj0iU3RhY2tlZFByb2plY3QiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI5MDA3IiBCb3VuZHM9IjEsNSIgTmFtZT0iU3RhY2tlZE1kaSIgQWxpYXM9IkFuYWx5c2lzIFdpbmRvdyIgSWNvbj0iU3RhY2tlZE1kaSIgLz4NCiAgICAgICAgPC9Hcm91cD4NCg0KICAgICAgICA8R3JvdXAgTmFtZT0iV2luZG93TGF5b3V0IiBBbGlhcz0iV2luZG93IExheW91dCI+DQogICAgICAgICAgICA8Q21kIElEPSI5MDExIiBCb3VuZHM9IjAsMCIgTmFtZT0iV2luZG93TGF5b3V0SCIgSWNvbk9ubHk9IjEiIFRpcHM9Ikhvcml6b250YWwgTGF5b3V0IiBJY29uPSJXaW5kb3dMYXlvdXRIIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTAxMiIgQm91bmRzPSIxLDAiIE5hbWU9IldpbmRvd0xheW91dFYiIEljb25Pbmx5PSIxIiBUaXBzPSJWZXJ0aWNhbCBMYXlvdXQiIEljb249IldpbmRvd0xheW91dFYiIC8+DQogICAgICAgICAgICA8Q21kIElEPSI5MDEzIiBCb3VuZHM9IjAsMSIgTmFtZT0iV2luZG93TGF5b3V0VCIgSWNvbk9ubHk9IjEiIFRpcHM9IlRpbGUgTGF5b3V0IiBJY29uPSJXaW5kb3dMYXlvdXRUIiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTAxNCIgQm91bmRzPSIxLDEiIE5hbWU9IldpbmRvd0xheW91dEMiIEljb25Pbmx5PSIxIiBUaXBzPSJDb2xsYXBzZSBMYXlvdXQiIEljb249IldpbmRvd0xheW91dEMiIC8+DQogICAgICAgIDwvR3JvdXA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9IkNsb3NlIiBBbGlhcz0iQ2xvc2UiPg0KICAgICAgICAgICAgPENtZCBJRD0iOTAyMSIgQm91bmRzPSIwLDAiIE5hbWU9IkNsb3NlQ3VyV25kIiBBbGlhcz0iQ2xvc2UgQ3VycmVudCIgSWNvbj0iQ2xvc2VBbGxXaW5kb3ciIC8+DQogICAgICAgICAgICA8Q21kIElEPSI5MDIyIiBCb3VuZHM9IjEsMCIgTmFtZT0iQ2xvc2VBbGxXbmRzIiBBbGlhcz0iQ2xvc2UgQWxsIiBJY29uPSJDbG9zZUFsbFdpbmRvdyIgLz4NCiAgICAgICAgICAgIDxDbWQgSUQ9IjkwMjMiIEJvdW5kcz0iMCwxIiBOYW1lPSJQcmV2V25kIiBBbGlhcz0iUHJldmlvdXMiIEljb25Pbmx5PSIxIiBJY29uPSJVcCIgVGlwcz0iUHJldmlvdXMgV2luZG93IiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iOTAyNCIgQm91bmRzPSIxLDEiIE5hbWU9Ik5leHRXbmQiIEFsaWFzPSJOZXh0IiBJY29uT25seT0iMSIgSWNvbj0iRG93biIgVGlwcz0iTmV4dCBXaW5kb3ciIC8+DQogICAgICAgICAgICA8Q21kIElEPSI5MDI1IiBCb3VuZHM9IjAsMiwyLDEiIFR5cGU9IjciIE5hbWU9Ikxpc3RXeFduZHMiIEFsaWFzPSJXaW5kb3dzIiAvPg0KICAgICAgICA8L0dyb3VwPg0KDQogICAgPC9UYWI+DQoNCiAgICA8VGFiIElEPSIxMCIgTmFtZT0iSGVscCIgQWxpYXM9IkhlbHAiID4NCg0KICAgICAgICA8R3JvdXAgTmFtZT0iSGVscCIgQWxpYXM9IkhlbHAiPg0KICAgICAgICAgICAgPENtZCBJRD0iMTAwMDEiIEJvdW5kcz0iMCwwLDIsMSIgTmFtZT0iTG9nVmlldyIgQWxpYXM9IkxvZyBWaWV3KEwpIiBJY29uPSJMb2dWaWV3IiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMTAwMDIiIEJvdW5kcz0iMCwxLDIsMSIgTmFtZT0iSGVscCIgQWxpYXM9IkhlbHAoSCkiIEljb249IkhlbHAiIC8+DQogICAgICAgICAgICA8Q21kIElEPSIxMDAwOCIgQm91bmRzPSIwLDIsMiwxIiBOYW1lPSJVcGRhdGVMaXN0cyIgQWxpYXM9IlVwZGF0ZSBMaXN0cyhJKSIgSWNvbj0iVXBkYXRlTGlzdHMiIC8+DQogICAgICAgIDwvR3JvdXA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9IkxhbmciIEFsaWFzPSJMYW5ndWFnZSI+DQogICAgICAgICAgIDxDbWQgSUQ9IjEwMDA5IiBCb3VuZHM9IjAsMCwyLDEiIE5hbWU9IkxhbmdTd2FwIiBBbGlhcz0iU3dhcCBsYW5ndWFnZSIgSWNvbj0iTGFuZ1N3YXAiIC8+DQogICAgICAgIDwvR3JvdXA+DQoNCiAgICAgICAgPEdyb3VwIE5hbWU9IkFib3V0IiBBbGlhcz0iQWJvdXQiPg0KICAgICAgICAgICAgPENtZCBJRD0iMTAwMDMiIEJvdW5kcz0iMCwwLDIsMSIgTmFtZT0iQWJvdXQiIEFsaWFzPSJBYm91dChBKSIgSWNvbj0iV1RBSUFib3V0IiAvPg0KICAgICAgICAgICAgPENtZCBJRD0iMTAwMDQiIEJvdW5kcz0iMSwwIiBOYW1lPSJBYm91dFF0IiBBbGlhcz0iQWJvdXQgUXQoUSkiIEljb249IlF0IiBWaXNpYmxlPSIwIiAvPg0KICAgICAgICA8L0dyb3VwPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJMb2dpbiIgQWxpYXM9IkxvZ2luKERlYnVnKSI+DQogICAgICAgICAgICA8Q21kIElEPSIxMDAwNyIgQm91bmRzPSIwLDAiIE5hbWU9IlJlZ2lzdGVyIiBBbGlhcz0iKERlYnVnKVNvZnR3YXJlIFJlZ2lzdHJhdGlvbihSKSIgSWNvbj0iUmVnaXN0ZXIiIC8+DQogICAgICAgICAgICA8Q21kIElEPSIxMDAwNSIgQm91bmRzPSIxLDAiIE5hbWU9IkxvZ2luIiBBbGlhcz0iKERlYnVnKVVzZXIgTG9naW4oVSkiIEljb249IkxvZ2luIiAvPg0KICAgICAgICA8L0dyb3VwPg0KDQogICAgICAgIDxHcm91cCBOYW1lPSJEZWJ1ZyIgQWxpYXM9IkRlYnVnKERlYnVnKSI+DQogICAgICAgICAgICA8Q21kIElEPSIxMDAwNiIgQm91bmRzPSIwLDAsMiwxIiBOYW1lPSIoRGVidWcpIFN1bSBQYXJhbWV0ZXJzIiBBbGlhcz0iKERlYnVnKVN1bW1hcml6ZSBNb2RlbCBQYXJhbWV0ZXJzIiBJY29uPSJTdW1QYXJhIiAvPg0KICAgICAgIDwvR3JvdXA+DQogICAgPC9UYWI+DQoNCjwvUmliYm9uPg0K
\ 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 8cdbc9b..32bc151 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 42ef643..e5a7886 100644
--- a/Bin/Config/Lang/cn/nmNum_cn.ts
+++ b/Bin/Config/Lang/cn/nmNum_cn.ts
@@ -6556,4 +6556,229 @@ Average pressure in contour: %2 MPa
3D视图
+
+ nmWxPropertyInterpolationDlg
+
+ Property Interpolation
+ 属性插值
+
+
+ Dataset:
+ 数据组:
+
+
+ Add dataset
+ 新建数据组
+
+
+ Delete dataset
+ 删除数据组
+
+
+ Dataset #%1
+ 数据组 #%1
+
+
+ Property:
+ 属性:
+
+
+ Permeability k
+ 渗透率 k
+
+
+ Permeability k (mD)
+ 渗透率 k(mD)
+
+
+ Porosity phi
+ 孔隙度 phi
+
+
+ Reservoir thickness h
+ 储层厚度 h
+
+
+ Reservoir thickness h (m)
+ 储层厚度 h(m)
+
+
+ Name:
+ 名称:
+
+
+ Permeability
+ 渗透率
+
+
+ Measurement Points
+ 测点数据
+
+
+ New value:
+ 新测点值:
+
+
+ Select on Map
+ 地图选点
+
+
+ X
+ X
+
+
+ Y
+ Y
+
+
+ Value
+ 数值
+
+
+ Delete Selected
+ 删除所选
+
+
+ Clear
+ 清空
+
+
+ Show measurement points
+ 显示测点
+
+
+ Show labels
+ 显示标签
+
+
+ Clear measurement points before changing the property.
+ 清空测点后可修改属性。
+
+
+ Kriging Parameters
+ 克里金参数
+
+
+ Nugget:
+ 块金值:
+
+
+ Sill:
+ 基台值:
+
+
+ Range:
+ 变程:
+
+
+ Model:
+ 模型:
+
+
+ Spherical (0)
+ 球状模型(0)
+
+
+ Exponential (1)
+ 指数模型(1)
+
+
+ Gaussian (2)
+ 高斯模型(2)
+
+
+ Use Interpolation in Solver
+ 求解时使用插值
+
+
+ Preview
+ 预览
+
+
+ Close
+ 关闭
+
+
+ Preview Failed
+ 预览失败
+
+
+ Please create a valid reservoir boundary before previewing.
+ 请先创建有效的储层边界,再进行预览。
+
+
+
+ nmWxPropertyInterpolationPreviewDlg
+
+ Interpolation Preview
+ 插值预览
+
+
+ Close
+ 关闭
+
+
+
+ nmCalculationUtils
+
+ No interpolation points are available.
+ 没有可用的待插值点。
+
+
+ At least two measurement points are required.
+ 至少需要两个测点。
+
+
+ Measurement point coordinates and values do not match.
+ 测点坐标与测点值的数量不一致。
+
+
+ Kriging parameters are invalid.
+ Kriging 参数无效。
+
+
+ The Kriging model is invalid.
+ Kriging 模型无效。
+
+
+ An interpolation point contains an invalid coordinate.
+ 待插值点中包含无效坐标。
+
+
+ A measurement point contains invalid data.
+ 测点中包含无效数据。
+
+
+ Measurement point coordinates cannot be duplicated.
+ 测点坐标不能重复。
+
+
+ The solver license file was not found.
+ 未找到求解器许可证文件。
+
+
+ Failed to load HX_NWTM.dll.
+ 加载 HX_NWTM.dll 失败。
+
+
+ The Kriging interface was not found in HX_NWTM.dll.
+ HX_NWTM.dll 中没有找到 Kriging 接口。
+
+
+ Kriging calculation failed: %1
+ Kriging 计算失败:%1
+
+
+ Kriging calculation failed.
+ Kriging 计算失败。
+
+
+ The Kriging result count does not match the interpolation points.
+ Kriging 结果数量与待插值点数量不一致。
+
+
+ The Kriging result contains an invalid value.
+ Kriging 结果中包含无效数值。
+
+
diff --git a/Bin/Res/Icon/NmInterpolation.png b/Bin/Res/Icon/NmInterpolation.png
new file mode 100644
index 0000000..c434a5b
Binary files /dev/null and b/Bin/Res/Icon/NmInterpolation.png differ
diff --git a/Bin/XmlFiles/MenuDefines_Ribbon_cn.xml b/Bin/XmlFiles/MenuDefines_Ribbon_cn.xml
index 7209158..1b63833 100644
--- a/Bin/XmlFiles/MenuDefines_Ribbon_cn.xml
+++ b/Bin/XmlFiles/MenuDefines_Ribbon_cn.xml
@@ -248,6 +248,7 @@
+
diff --git a/Bin/XmlFiles/MenuDefines_Ribbon_en.xml b/Bin/XmlFiles/MenuDefines_Ribbon_en.xml
index d074a73..c38f242 100644
--- a/Bin/XmlFiles/MenuDefines_Ribbon_en.xml
+++ b/Bin/XmlFiles/MenuDefines_Ribbon_en.xml
@@ -246,6 +246,7 @@
+
diff --git a/Include/nmNum/nmCalculation/nmCalculationUtils.h b/Include/nmNum/nmCalculation/nmCalculationUtils.h
index 7a40459..76a5faa 100644
--- a/Include/nmNum/nmCalculation/nmCalculationUtils.h
+++ b/Include/nmNum/nmCalculation/nmCalculationUtils.h
@@ -2,6 +2,8 @@
#define NMCALCULATIONUTILS_H
#include
+#include
+#include
#include "nmCalculation_global.h"
#include "nmCalculationDefine.h"
#include
@@ -16,6 +18,20 @@ class NMCALCULATION_EXPORT nmCalculationUtils {
static bool removeDirectory(const QString &dirPath);
static bool writeFile(const QStringList& content, const QString &filePath);
static QStringList readFile(const QString & filePath);
+
+ // 调用求解器Kriging接口,对targetPoints中的坐标依次进行属性插值.
+ // measurementPoints与measurementValues按下标一一对应.
+ // 成功时outputValues与targetPoints数量相同且顺序一致;失败时清空outputValues.
+ static bool calculateKriging(const QVector& targetPoints,
+ const QVector& measurementPoints,
+ const QVector& measurementValues,
+ double nugget,
+ double sill,
+ double range,
+ int model,
+ const QString& licensePath,
+ QVector& outputValues,
+ QString* errorMessage = 0);
};
#endif // NMCALCULATIONUTILS_H
diff --git a/Include/nmNum/nmData/nmDataAnalyzeManager.h b/Include/nmNum/nmData/nmDataAnalyzeManager.h
index c908ac2..a2a0f4e 100644
--- a/Include/nmNum/nmData/nmDataAnalyzeManager.h
+++ b/Include/nmNum/nmData/nmDataAnalyzeManager.h
@@ -51,6 +51,58 @@ struct BackgroundImageInfo {
QImage objImage; // 具体的QImage对象
};
+/* 插值测点数据 */
+struct NM_DATA_EXPORT nmPropertyInterpolationPointData {
+ nmPropertyInterpolationPointData()
+ : x(0.0), y(0.0), value(0.0)
+ {
+ }
+
+ nmPropertyInterpolationPointData(double xValue, double yValue, double propertyValue)
+ : x(xValue), y(yValue), value(propertyValue)
+ {
+ }
+
+ double x;
+ double y;
+ double value;
+};
+
+/* 一组属性插值数据及其Kriging参数 */
+struct NM_DATA_EXPORT nmPropertyInterpolationDataSet {
+ nmPropertyInterpolationDataSet()
+ : property("k"),
+ xDisplayUnit("m"),
+ yDisplayUnit("m"),
+ valueDisplayUnit("mD"),
+ rangeDisplayUnit("m"),
+ useForCalculation(false),
+ showPoints(true),
+ showLabels(true),
+ nugget(0.01),
+ sill(100.0),
+ range(1000.0),
+ model(0)
+ {
+ }
+
+ QString name;
+ QString property;
+ // 仅记录界面显示单位;坐标、Range及属性值始终按基准单位保存.
+ QString xDisplayUnit;
+ QString yDisplayUnit;
+ QString valueDisplayUnit;
+ QString rangeDisplayUnit;
+ bool useForCalculation;
+ QVector points;
+ bool showPoints;
+ bool showLabels;
+ double nugget;
+ double sill;
+ double range;
+ int model;
+};
+
enum NM_SOLVER_MODEL_TYPE {
SMT_Oil_ConstPvt = 1,
SMT_Oil_VariablePvt = 2,
@@ -433,6 +485,10 @@ class NM_DATA_EXPORT nmDataAnalyzeManager : public ZxDataObjectBin
// 获取背景图片信息
const BackgroundImageInfo& getBackgroundImageInfo() const;
+ /* 获取及设置属性插值数据组 */
+ QVector getPropertyInterpolationDataSets() const;
+ void setPropertyInterpolationDataSets(const QVector& dataSets);
+
// 统一的读写整个项目数据的方法
// @param filePath JSON文件的路径
// @return 读取成功返回 true,否则返回 false
@@ -647,6 +703,9 @@ class NM_DATA_EXPORT nmDataAnalyzeManager : public ZxDataObjectBin
// 显示设置信息
QVector m_vecDisplaySettings;
+ /* 属性插值数据组 */
+ QVector m_vecPropertyInterpolationDataSets;
+
// 背景图片信息
BackgroundImageInfo m_backgroundImageInfo;
diff --git a/Include/nmNum/nmPlot/nmGuiPlot.h b/Include/nmNum/nmPlot/nmGuiPlot.h
index 3a57ae6..9bb7cce 100644
--- a/Include/nmNum/nmPlot/nmGuiPlot.h
+++ b/Include/nmNum/nmPlot/nmGuiPlot.h
@@ -42,6 +42,9 @@ class NM_PLOT_EXPORT nmGuiPlot : public iGuiPlot {
// Action命令执行
virtual bool runAction(QString sAction) override;
+ // 取消当前地图绘图操作.
+ void cancelActiveTools();
+
// 创建添加一个Obj
nmObjBase* appendOneObj(NM_Obj_Type o, QString& sName, QVector& vec);
nmObjBase* _createOneObj(NM_Obj_Type o, QString& sName);
diff --git a/Include/nmNum/nmPlot/nmGuiPlotCmdHelper.h b/Include/nmNum/nmPlot/nmGuiPlotCmdHelper.h
index 58a8fd4..8c026d9 100644
--- a/Include/nmNum/nmPlot/nmGuiPlotCmdHelper.h
+++ b/Include/nmNum/nmPlot/nmGuiPlotCmdHelper.h
@@ -19,6 +19,9 @@ public:
virtual bool runAction(QString sAction) override;
+ // 取消当前地图绘图操作,并恢复默认操作状态.
+ void cancelActiveTools();
+
// 插入背景
void insertBkImg();
diff --git a/Include/nmNum/nmSubWnd/nmSubWndMain.h b/Include/nmNum/nmSubWnd/nmSubWndMain.h
index 30c88c5..b7ed138 100644
--- a/Include/nmNum/nmSubWnd/nmSubWndMain.h
+++ b/Include/nmNum/nmSubWnd/nmSubWndMain.h
@@ -205,6 +205,8 @@ class NM_SUB_WND_EXPORT nmSubWndMain : public iSubWndBaseFit {
QWidget* showMeasureDialog();
// 显示模型位置对话框
QWidget* showPointerPosDialog();
+ // 显示属性插值对话框
+ QWidget* showPropertyInterpolationDialog();
void bindDialogCmdDestroyed(QWidget* dialog, int nId);
void bindMeasureDialog(QWidget* measureDlg);
bool isDialogCmdOpened(int nId) const;
diff --git a/Include/nmNum/nmSubWxs/nmWxPropertyInterpolationDlg.h b/Include/nmNum/nmSubWxs/nmWxPropertyInterpolationDlg.h
new file mode 100644
index 0000000..c264ade
--- /dev/null
+++ b/Include/nmNum/nmSubWxs/nmWxPropertyInterpolationDlg.h
@@ -0,0 +1,167 @@
+#ifndef NMWXPROPERTYINTERPOLATIONDLG_H
+#define NMWXPROPERTYINTERPOLATIONDLG_H
+
+#include "iDlgBase.h"
+#include "nmDataAnalyzeManager.h"
+#include "nmSubWxs_global.h"
+
+#include
+#include
+#include
+
+class QCheckBox;
+class QComboBox;
+class QDoubleSpinBox;
+class QEvent;
+class QLineEdit;
+class QPointF;
+class QPushButton;
+class QTableWidget;
+class QTableWidgetItem;
+class QTimer;
+class nmGuiPlot;
+class nmObjPoint;
+class nmWxPropertyInterpolationPreviewDlg;
+
+class NM_SUB_WXS_EXPORT nmWxPropertyInterpolationDlg : public iDlgBase
+{
+ Q_OBJECT
+
+public:
+ explicit nmWxPropertyInterpolationDlg(nmGuiPlot* plot,
+ nmDataAnalyzeManager* dataManager,
+ QWidget* parent = 0);
+ ~nmWxPropertyInterpolationDlg();
+
+protected:
+ bool eventFilter(QObject* watched, QEvent* event);
+
+private slots:
+ void onDataSetChanged(int index);
+ void onAddDataSet();
+ void onDeleteDataSet();
+ void onDataSetNameChanged(const QString& name);
+ // 当前数据组属性及显示单位变化.
+ void onCurrentDataSetPropertyChanged();
+ void onCurrentDataSetEdited();
+ void onXDisplayUnitChanged(const QString& unit);
+ void onYDisplayUnitChanged(const QString& unit);
+ void onValueDisplayUnitChanged(const QString& unit);
+ void onRangeDisplayUnitChanged(const QString& unit);
+ // 正式求解使用的数据组变化.
+ void onCalculationSelectionChanged();
+ void onMapPickToggled(bool checked);
+ void onMapClicked(const QPointF& position);
+ void onPointSelectionChanged();
+ void onPointItemChanged(QTableWidgetItem* item);
+ void onDeleteSelectedPoint();
+ void onClearPoints();
+ void onShowPointsToggled(bool checked);
+ void onShowLabelsToggled(bool checked);
+ void onPreview();
+ void refreshPreview();
+
+private:
+ // 初始化界面及持久化数据组.
+ void initInterpolationUI();
+ void initializeDataSets();
+ nmPropertyInterpolationDataSet createDefaultDataSet();
+ QString nextDataSetName();
+ void loadDataSet(int index);
+ void clearCurrentDataSet();
+ void saveCurrentDataSet();
+ // 单位控件只维护界面显示状态;插值数据始终按求解器基准单位保存.
+ void updateUnitControls(nmPropertyInterpolationDataSet& dataSet);
+ void updatePointDisplayValues();
+ void clearPointRows();
+ void updatePointRowNumbers();
+ void syncDataSetsToManager(bool markModified);
+ void updateDataSetButtons();
+ // 管理正式求解时k、phi和h各自使用的插值数据组.
+ void updateCalculationDataSetControls();
+ void updateCalculationDataSetControl(const QString& property,
+ QCheckBox* checkBox,
+ QComboBox* comboBox);
+ void saveCalculationSelection(const QString& property,
+ QCheckBox* checkBox,
+ QComboBox* comboBox);
+
+ // 管理测点表格和地图上的临时标记.
+ void appendPoint(const QPointF& valuePoint);
+ void appendPointRow(const nmPropertyInterpolationPointData& point,
+ const QString& markerName);
+ QString createMarker(const QPointF& valuePosition,
+ double value,
+ bool showPoints,
+ bool showLabels);
+ void createMarkersForAllDataSets();
+ void removeDataSetMarkers(int dataSetIndex);
+ void removeAllMarkers();
+ QString markerNameAt(int row) const;
+ nmObjPoint* markerByName(const QString& markerName) const;
+ nmObjPoint* markerAt(int row) const;
+ void removeMarkerByName(const QString& markerName);
+ void clearTableSelection();
+ void updatePointButtons();
+ void updateCurrentMarkerVisibility();
+ void schedulePreviewRefresh();
+ void updatePreviewWindow(bool activateWindow);
+ void showPreviewError(const QString& message, bool activateWindow);
+
+private:
+ QPointer m_pPlot;
+ QPointer m_pDataManager;
+
+ // 多组插值数据.
+ QComboBox* m_pDataSetCombo;
+ QPushButton* m_pAddDataSetButton;
+ QPushButton* m_pDeleteDataSetButton;
+ QVector m_vecDataSets;
+ // 与数据组、测点下标一一对应,仅保存地图临时标记的对象名称.
+ QVector m_vecMarkerNames;
+ int m_nCurrentDataSetIndex;
+ int m_nNextPointId;
+ // 加载界面数据时阻止控件信号反向修改当前数据组.
+ bool m_bUpdatingUi;
+
+ // 当前数据组的属性及名称.
+ QComboBox* m_pPropertyCombo;
+ QLineEdit* m_pNameEdit;
+
+ // 测点数据录入.
+ QDoubleSpinBox* m_pNewValueSpin;
+ // 新值单位与表格Value列单位保持同步.
+ QComboBox* m_pNewValueUnitCombo;
+ QPushButton* m_pMapPickButton;
+ QTableWidget* m_pPointTable;
+ // 表格第0行中的X、Y和Value显示单位.
+ QComboBox* m_pXUnitCombo;
+ QComboBox* m_pYUnitCombo;
+ QComboBox* m_pValueUnitCombo;
+ QPushButton* m_pDeletePointButton;
+ QPushButton* m_pClearPointsButton;
+ QCheckBox* m_pShowPointsCheck;
+ QCheckBox* m_pShowLabelsCheck;
+
+ // Kriging插值参数.
+ QDoubleSpinBox* m_pNuggetSpin;
+ QDoubleSpinBox* m_pSillSpin;
+ QDoubleSpinBox* m_pRangeSpin;
+ QComboBox* m_pRangeUnitCombo;
+ QComboBox* m_pModelCombo;
+
+ // 正式求解时各属性使用的数据组.
+ QCheckBox* m_pUseKCheck;
+ QComboBox* m_pKCalculationDataSetCombo;
+ QCheckBox* m_pUsePhiCheck;
+ QComboBox* m_pPhiCalculationDataSetCombo;
+ QCheckBox* m_pUseHCheck;
+ QComboBox* m_pHCalculationDataSetCombo;
+
+ // 插值结果预览.
+ QPushButton* m_pPreviewButton;
+ QPointer m_pPreviewDialog;
+ QTimer* m_pPreviewRefreshTimer;
+};
+
+#endif // NMWXPROPERTYINTERPOLATIONDLG_H
diff --git a/Include/nmNum/nmSubWxs/nmWxPropertyInterpolationPreviewDlg.h b/Include/nmNum/nmSubWxs/nmWxPropertyInterpolationPreviewDlg.h
new file mode 100644
index 0000000..e665190
--- /dev/null
+++ b/Include/nmNum/nmSubWxs/nmWxPropertyInterpolationPreviewDlg.h
@@ -0,0 +1,71 @@
+#ifndef NMWXPROPERTYINTERPOLATIONPREVIEWDLG_H
+#define NMWXPROPERTYINTERPOLATIONPREVIEWDLG_H
+
+#include "iDlgBase.h"
+#include "nmSubWxs_global.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+class QVTKWidget;
+
+// 网格属性插值结果的独立VTK预览对话框.
+class NM_SUB_WXS_EXPORT nmWxPropertyInterpolationPreviewDlg : public iDlgBase
+{
+public:
+ explicit nmWxPropertyInterpolationPreviewDlg(
+ const QString& dataSetName,
+ const QString& scalarTitle,
+ const QRectF& bounds,
+ int columnCount,
+ int rowCount,
+ const QVector& interpolationValues,
+ const QVector& measurementPoints,
+ const QVector& measurementValues,
+ const QVector& outlinePoints,
+ const QVector& wellPoints,
+ const QStringList& wellNames,
+ bool showMeasurementPoints,
+ bool showMeasurementLabels,
+ QWidget* parent = 0);
+
+ void updatePreview(const QString& dataSetName,
+ const QString& scalarTitle,
+ const QRectF& bounds,
+ int columnCount,
+ int rowCount,
+ const QVector& interpolationValues,
+ const QVector& measurementPoints,
+ const QVector& measurementValues,
+ const QVector& outlinePoints,
+ const QVector& wellPoints,
+ const QStringList& wellNames,
+ bool showMeasurementPoints,
+ bool showMeasurementLabels);
+ void showMessage(const QString& dataSetName, const QString& message);
+
+ virtual QSize sizeHint() const;
+
+private:
+ void initializeRenderer(const QString& scalarTitle,
+ const QRectF& bounds,
+ int columnCount,
+ int rowCount,
+ const QVector& interpolationValues,
+ const QVector& measurementPoints,
+ const QVector& measurementValues,
+ const QVector& outlinePoints,
+ const QVector& wellPoints,
+ const QStringList& wellNames,
+ bool showMeasurementPoints,
+ bool showMeasurementLabels);
+
+private:
+ QVTKWidget* m_pVtkWidget;
+};
+
+#endif // NMWXPROPERTYINTERPOLATIONPREVIEWDLG_H
diff --git a/Src/nmNum/nmCalculation/nmCalculationDllPebiSolverTask.cpp b/Src/nmNum/nmCalculation/nmCalculationDllPebiSolverTask.cpp
index e8db3a5..7951652 100644
--- a/Src/nmNum/nmCalculation/nmCalculationDllPebiSolverTask.cpp
+++ b/Src/nmNum/nmCalculation/nmCalculationDllPebiSolverTask.cpp
@@ -16,6 +16,7 @@
#include "nmDataTimeStepSetting.h"
#include "nmCalculationPebiGrid.h"
+#include "nmCalculationUtils.h"
#include "nmDataAnalyzeManager.h"
#include "nmDataPvtParaForPebi.h"
@@ -52,6 +53,111 @@ bool isFiniteSolverNumber(double value)
#endif
}
+// 将启用的数据组插值到全部网格单元中心,并覆盖对应的求解器属性数组.
+bool applyPropertyInterpolation(
+ HX_NWTM_MODEL_INPUT& modelInput,
+ const QVector& dataSets,
+ const QString& licensePath,
+ QString& errorMessage)
+{
+ bool hasEnabledDataSet = false;
+ for(int i = 0; i < dataSets.size(); ++i) {
+ if(dataSets[i].useForCalculation) {
+ hasEnabledDataSet = true;
+ break;
+ }
+ }
+
+ if(!hasEnabledDataSet) {
+ return true;
+ }
+
+ QVector targetPoints;
+ targetPoints.reserve(static_cast(modelInput.GRID.Trinodexy.size()));
+ for(size_t cellIndex = 0;
+ cellIndex < modelInput.GRID.Trinodexy.size(); ++cellIndex) {
+ const dVec1& cellPosition = modelInput.GRID.Trinodexy[cellIndex];
+ if(cellPosition.size() < 2) {
+ errorMessage = QString("Grid cell %1 has no valid center coordinate.")
+ .arg(static_cast(cellIndex));
+ return false;
+ }
+ targetPoints.append(QPointF(cellPosition[0], cellPosition[1]));
+ }
+
+ bool kApplied = false;
+ bool phiApplied = false;
+ bool hApplied = false;
+ for(int dataSetIndex = 0; dataSetIndex < dataSets.size(); ++dataSetIndex) {
+ const nmPropertyInterpolationDataSet& dataSet = dataSets[dataSetIndex];
+ if(!dataSet.useForCalculation) {
+ continue;
+ }
+
+ dVec1* solverValues = NULL;
+ bool* propertyApplied = NULL;
+ if(dataSet.property == "k") {
+ solverValues = &modelInput.Base.k;
+ propertyApplied = &kApplied;
+ } else if(dataSet.property == "phi") {
+ solverValues = &modelInput.Base.phi;
+ propertyApplied = &phiApplied;
+ } else if(dataSet.property == "h") {
+ solverValues = &modelInput.Base.h;
+ propertyApplied = &hApplied;
+ } else {
+ errorMessage = QString("Dataset '%1' has an unknown property.")
+ .arg(dataSet.name);
+ return false;
+ }
+
+ if(*propertyApplied) {
+ errorMessage = QString(
+ "More than one dataset is enabled for property %1.")
+ .arg(dataSet.property);
+ return false;
+ }
+
+ QVector measurementPoints;
+ QVector measurementValues;
+ measurementPoints.reserve(dataSet.points.size());
+ measurementValues.reserve(dataSet.points.size());
+ for(int pointIndex = 0; pointIndex < dataSet.points.size(); ++pointIndex) {
+ const nmPropertyInterpolationPointData& point = dataSet.points[pointIndex];
+ measurementPoints.append(QPointF(point.x, point.y));
+ measurementValues.append(point.value);
+ }
+
+ QVector interpolationValues;
+ QString calculationError;
+ if(!nmCalculationUtils::calculateKriging(
+ targetPoints,
+ measurementPoints,
+ measurementValues,
+ dataSet.nugget,
+ dataSet.sill,
+ dataSet.range,
+ dataSet.model,
+ licensePath,
+ interpolationValues,
+ &calculationError)) {
+ errorMessage = QString("Dataset '%1': %2")
+ .arg(dataSet.name)
+ .arg(calculationError);
+ return false;
+ }
+
+ solverValues->resize(interpolationValues.size());
+ for(int valueIndex = 0; valueIndex < interpolationValues.size(); ++valueIndex) {
+ // 插值数据已经使用求解器基准单位,结果可直接按网格顺序写入.
+ (*solverValues)[valueIndex] = interpolationValues[valueIndex];
+ }
+ *propertyApplied = true;
+ }
+
+ return true;
+}
+
bool isReasonableLogLogValue(double value)
{
const double maxReasonableAbsValue = 1.0e12;
@@ -485,6 +591,21 @@ bool nmCalculationDllPebiSolverTask::execPebiMode()
p0.Base.h = dVec1(cellCount, pReservoirData->getThickness().getValue().toDouble());
}
+ // 未启用的属性保留上面的单值数组;启用后才使用所选数据组覆盖.
+ QString interpolationError;
+ if(!applyPropertyInterpolation(
+ p0,
+ pDataInstance->getPropertyInterpolationDataSets(),
+ pDataInstance->getLicensePath(),
+ interpolationError)) {
+ QString logMessage = QString("Property interpolation failed: %1")
+ .arg(interpolationError);
+ qWarning() << logMessage;
+ zxLogInstance::getInstance()->writeLogF(logMessage);
+ FreeLibrary(dll);
+ return false;
+ }
+
// 获取时间步长
nmDataTimeStepSetting* pTimeStepSetting = pDataInstance->getTimeStep();
if(pTimeStepSetting) {
diff --git a/Src/nmNum/nmCalculation/nmCalculationUtils.cpp b/Src/nmNum/nmCalculation/nmCalculationUtils.cpp
index fdb33d9..5aca5ac 100644
--- a/Src/nmNum/nmCalculation/nmCalculationUtils.cpp
+++ b/Src/nmNum/nmCalculation/nmCalculationUtils.cpp
@@ -4,7 +4,35 @@
#include
#include
#include
+#include
#include
+#include
+
+#include "pch.h"
+
+namespace
+{
+QString krigingText(const char* sourceText)
+{
+ return QCoreApplication::translate("nmCalculationUtils", sourceText);
+}
+
+bool isFiniteValue(double value)
+{
+#ifdef _MSC_VER
+ return _finite(value) != 0;
+#else
+ return std::isfinite(value);
+#endif
+}
+
+void setKrigingError(QString* errorMessage, const QString& message)
+{
+ if(errorMessage != NULL) {
+ *errorMessage = message;
+ }
+}
+}
nmCalculationUtils::nmCalculationUtils() {
}
@@ -159,3 +187,165 @@ QStringList nmCalculationUtils::readFile(const QString &filePath) {
return content;
}
+bool nmCalculationUtils::calculateKriging(
+ const QVector& targetPoints,
+ const QVector& measurementPoints,
+ const QVector& measurementValues,
+ double nugget,
+ double sill,
+ double range,
+ int model,
+ const QString& licensePath,
+ QVector& outputValues,
+ QString* errorMessage)
+{
+ outputValues.clear();
+ setKrigingError(errorMessage, QString());
+
+ if(targetPoints.isEmpty()) {
+ setKrigingError(errorMessage, krigingText("No interpolation points are available."));
+ return false;
+ }
+
+ if(measurementPoints.size() < 2) {
+ setKrigingError(errorMessage,
+ krigingText("At least two measurement points are required."));
+ return false;
+ }
+
+ if(measurementPoints.size() != measurementValues.size()) {
+ setKrigingError(errorMessage,
+ krigingText("Measurement point coordinates and values do not match."));
+ return false;
+ }
+
+ if(!isFiniteValue(nugget) || !isFiniteValue(sill) ||
+ !isFiniteValue(range) || nugget < 0.0 || sill <= 0.0 || range <= 0.0) {
+ setKrigingError(errorMessage, krigingText("Kriging parameters are invalid."));
+ return false;
+ }
+
+ if(model < 0 || model > 2) {
+ setKrigingError(errorMessage, krigingText("The Kriging model is invalid."));
+ return false;
+ }
+
+ for(int i = 0; i < targetPoints.size(); ++i) {
+ if(!isFiniteValue(targetPoints[i].x()) || !isFiniteValue(targetPoints[i].y())) {
+ setKrigingError(errorMessage,
+ krigingText("An interpolation point contains an invalid coordinate."));
+ return false;
+ }
+ }
+
+ for(int i = 0; i < measurementPoints.size(); ++i) {
+ if(!isFiniteValue(measurementPoints[i].x()) ||
+ !isFiniteValue(measurementPoints[i].y()) ||
+ !isFiniteValue(measurementValues[i])) {
+ setKrigingError(errorMessage,
+ krigingText("A measurement point contains invalid data."));
+ return false;
+ }
+
+ for(int j = 0; j < i; ++j) {
+ if(measurementPoints[i] == measurementPoints[j]) {
+ setKrigingError(errorMessage,
+ krigingText("Measurement point coordinates cannot be duplicated."));
+ return false;
+ }
+ }
+ }
+
+ if(licensePath.isEmpty() || !QFileInfo(licensePath).exists()) {
+ setKrigingError(errorMessage, krigingText("The solver license file was not found."));
+ return false;
+ }
+
+ HMODULE dll = LoadLibrary(L"HX_NWTM.dll");
+ if(dll == NULL) {
+ setKrigingError(errorMessage, krigingText("Failed to load HX_NWTM.dll."));
+ return false;
+ }
+
+ typedef void (*HX_NWTM_KRINGING_Func)(HX_KRING_OUTPUT&,
+ const HX_KRING_INPUT,
+ std::string);
+ HX_NWTM_KRINGING_Func krigingFunction =
+ (HX_NWTM_KRINGING_Func)GetProcAddress(dll, "HX_NWTM_KRINGING");
+ if(krigingFunction == NULL) {
+ FreeLibrary(dll);
+ setKrigingError(errorMessage,
+ krigingText("The Kriging interface was not found in HX_NWTM.dll."));
+ return false;
+ }
+
+ // 求解器p参数每行保存{x, y},并保持targetPoints的原始顺序.
+ dVec2 targetData;
+ targetData.reserve(targetPoints.size());
+ for(int i = 0; i < targetPoints.size(); ++i) {
+ dVec1 point(2, 0.0);
+ point[0] = targetPoints[i].x();
+ point[1] = targetPoints[i].y();
+ targetData.push_back(point);
+ }
+
+ // 求解器v参数每行保存{x, y, value},坐标和值按相同下标配对.
+ dVec2 measurementData;
+ measurementData.reserve(measurementPoints.size());
+ for(int i = 0; i < measurementPoints.size(); ++i) {
+ dVec1 point(3, 0.0);
+ point[0] = measurementPoints[i].x();
+ point[1] = measurementPoints[i].y();
+ point[2] = measurementValues[i];
+ measurementData.push_back(point);
+ }
+
+ bool calculationSucceeded = true;
+ QString calculationError;
+
+ // 局部作用域保证求解器输入、输出对象在FreeLibrary前析构.
+ {
+ HX_KRING_INPUT input(nugget, sill, range, model,
+ targetData, measurementData);
+ HX_KRING_OUTPUT output;
+
+ try {
+ krigingFunction(output, input, licensePath.toStdString());
+ } catch(const std::exception& exception) {
+ calculationSucceeded = false;
+ calculationError = krigingText("Kriging calculation failed: %1")
+ .arg(QString::fromLocal8Bit(exception.what()));
+ } catch(...) {
+ calculationSucceeded = false;
+ calculationError = krigingText("Kriging calculation failed.");
+ }
+
+ if(calculationSucceeded &&
+ output.v.size() != static_cast(targetPoints.size())) {
+ calculationSucceeded = false;
+ calculationError = krigingText(
+ "The Kriging result count does not match the interpolation points.");
+ }
+
+ if(calculationSucceeded) {
+ outputValues.reserve(targetPoints.size());
+ for(size_t i = 0; i < output.v.size(); ++i) {
+ if(!isFiniteValue(output.v[i])) {
+ calculationSucceeded = false;
+ calculationError = krigingText(
+ "The Kriging result contains an invalid value.");
+ break;
+ }
+ outputValues.append(output.v[i]);
+ }
+ }
+ }
+
+ FreeLibrary(dll);
+ if(!calculationSucceeded) {
+ outputValues.clear();
+ setKrigingError(errorMessage, calculationError);
+ }
+ return calculationSucceeded;
+}
+
diff --git a/Src/nmNum/nmData/nmDataAnalyzeManager.cpp b/Src/nmNum/nmData/nmDataAnalyzeManager.cpp
index 87c9380..d615efd 100644
--- a/Src/nmNum/nmData/nmDataAnalyzeManager.cpp
+++ b/Src/nmNum/nmData/nmDataAnalyzeManager.cpp
@@ -65,6 +65,7 @@
#include "nmDataTimeStepSetting.h"
+#include
#include
#include
#include
@@ -3353,6 +3354,17 @@ const BackgroundImageInfo& nmDataAnalyzeManager::getBackgroundImageInfo() const
return m_backgroundImageInfo;
}
+QVector nmDataAnalyzeManager::getPropertyInterpolationDataSets() const
+{
+ return m_vecPropertyInterpolationDataSets;
+}
+
+void nmDataAnalyzeManager::setPropertyInterpolationDataSets(
+ const QVector& dataSets)
+{
+ m_vecPropertyInterpolationDataSets = dataSets;
+}
+
// 从 JSON 文件读取数据到 C++ 对象
bool nmDataAnalyzeManager::ReadProjectData(const QString & filePath)
{
@@ -3400,6 +3412,7 @@ bool nmDataAnalyzeManager::ReadProjectData(const QString & filePath)
}
m_vecLayers.clear();
+ m_vecPropertyInterpolationDataSets.clear();
if(m_reservoirData) {
delete m_reservoirData;
@@ -3517,7 +3530,96 @@ bool nmDataAnalyzeManager::ReadProjectData(const QString & filePath)
}
}
- // 解析 "Reservoir" 对象
+ /* 读取属性插值数据组 */
+ if(doc.HasMember("PropertyInterpolationDataSets") &&
+ doc["PropertyInterpolationDataSets"].IsArray()) {
+ const rapidjson::Value& dataSetsJson = doc["PropertyInterpolationDataSets"];
+
+ for(rapidjson::SizeType i = 0; i < dataSetsJson.Size(); ++i) {
+ const rapidjson::Value& dataSetJson = dataSetsJson[i];
+ if(!dataSetJson.IsObject()) {
+ continue;
+ }
+
+ nmPropertyInterpolationDataSet dataSet;
+ if(dataSetJson.HasMember("Name") && dataSetJson["Name"].IsString()) {
+ dataSet.name = QString::fromUtf8(dataSetJson["Name"].GetString());
+ }
+ if(dataSetJson.HasMember("Property") && dataSetJson["Property"].IsString()) {
+ dataSet.property = QString::fromUtf8(dataSetJson["Property"].GetString());
+ }
+ if(dataSet.property == "h") {
+ dataSet.valueDisplayUnit = "m";
+ }
+ else if(dataSet.property == "phi") {
+ dataSet.valueDisplayUnit.clear();
+ }
+ if(dataSetJson.HasMember("XDisplayUnit") &&
+ dataSetJson["XDisplayUnit"].IsString()) {
+ dataSet.xDisplayUnit = QString::fromUtf8(
+ dataSetJson["XDisplayUnit"].GetString());
+ }
+ if(dataSetJson.HasMember("YDisplayUnit") &&
+ dataSetJson["YDisplayUnit"].IsString()) {
+ dataSet.yDisplayUnit = QString::fromUtf8(
+ dataSetJson["YDisplayUnit"].GetString());
+ }
+ if(dataSetJson.HasMember("ValueDisplayUnit") &&
+ dataSetJson["ValueDisplayUnit"].IsString()) {
+ dataSet.valueDisplayUnit = QString::fromUtf8(
+ dataSetJson["ValueDisplayUnit"].GetString());
+ }
+ if(dataSetJson.HasMember("RangeDisplayUnit") &&
+ dataSetJson["RangeDisplayUnit"].IsString()) {
+ dataSet.rangeDisplayUnit = QString::fromUtf8(
+ dataSetJson["RangeDisplayUnit"].GetString());
+ }
+ if(dataSetJson.HasMember("UseForCalculation") &&
+ dataSetJson["UseForCalculation"].IsBool()) {
+ dataSet.useForCalculation = dataSetJson["UseForCalculation"].GetBool();
+ }
+ if(dataSetJson.HasMember("ShowPoints") && dataSetJson["ShowPoints"].IsBool()) {
+ dataSet.showPoints = dataSetJson["ShowPoints"].GetBool();
+ }
+ if(dataSetJson.HasMember("ShowLabels") && dataSetJson["ShowLabels"].IsBool()) {
+ dataSet.showLabels = dataSetJson["ShowLabels"].GetBool();
+ }
+ if(dataSetJson.HasMember("Nugget") && dataSetJson["Nugget"].IsNumber()) {
+ dataSet.nugget = dataSetJson["Nugget"].GetDouble();
+ }
+ if(dataSetJson.HasMember("Sill") && dataSetJson["Sill"].IsNumber()) {
+ dataSet.sill = dataSetJson["Sill"].GetDouble();
+ }
+ if(dataSetJson.HasMember("Range") && dataSetJson["Range"].IsNumber()) {
+ dataSet.range = dataSetJson["Range"].GetDouble();
+ }
+ if(dataSetJson.HasMember("Model") && dataSetJson["Model"].IsInt()) {
+ dataSet.model = dataSetJson["Model"].GetInt();
+ }
+
+ if(dataSetJson.HasMember("Points") && dataSetJson["Points"].IsArray()) {
+ const rapidjson::Value& pointsJson = dataSetJson["Points"];
+ for(rapidjson::SizeType pointIndex = 0; pointIndex < pointsJson.Size(); ++pointIndex) {
+ const rapidjson::Value& pointJson = pointsJson[pointIndex];
+ if(!pointJson.IsObject() ||
+ !pointJson.HasMember("X") || !pointJson["X"].IsNumber() ||
+ !pointJson.HasMember("Y") || !pointJson["Y"].IsNumber() ||
+ !pointJson.HasMember("Value") || !pointJson["Value"].IsNumber()) {
+ continue;
+ }
+
+ dataSet.points.append(nmPropertyInterpolationPointData(
+ pointJson["X"].GetDouble(),
+ pointJson["Y"].GetDouble(),
+ pointJson["Value"].GetDouble()));
+ }
+ }
+
+ m_vecPropertyInterpolationDataSets.append(dataSet);
+ }
+ }
+
+ /* 解析 "Reservoir" 对象 */
if(doc.HasMember("Reservoir") && doc["Reservoir"].IsObject()) {
m_reservoirData = new nmDataReservoir;
m_reservoirData->FromJsonValue(doc["Reservoir"]);
@@ -3736,6 +3838,55 @@ bool nmDataAnalyzeManager::WriteProjectData(const QString & filePath)
doc.AddMember("Layers", layersJsonArray, allocator);
+ /* 保存属性插值数据组;数值统一使用m、D等求解器基准单位 */
+ rapidjson::Value interpolationDataSetsJson(rapidjson::kArrayType);
+ for(int dataSetIndex = 0;
+ dataSetIndex < m_vecPropertyInterpolationDataSets.size();
+ ++dataSetIndex) {
+ const nmPropertyInterpolationDataSet& dataSet =
+ m_vecPropertyInterpolationDataSets[dataSetIndex];
+ rapidjson::Value dataSetJson(rapidjson::kObjectType);
+
+ QByteArray nameUtf8 = dataSet.name.toUtf8();
+ QByteArray propertyUtf8 = dataSet.property.toUtf8();
+ dataSetJson.AddMember("Name",
+ rapidjson::Value(nameUtf8.constData(), allocator).Move(), allocator);
+ dataSetJson.AddMember("Property",
+ rapidjson::Value(propertyUtf8.constData(), allocator).Move(), allocator);
+ QByteArray xDisplayUnitUtf8 = dataSet.xDisplayUnit.toUtf8();
+ QByteArray yDisplayUnitUtf8 = dataSet.yDisplayUnit.toUtf8();
+ QByteArray valueDisplayUnitUtf8 = dataSet.valueDisplayUnit.toUtf8();
+ QByteArray rangeDisplayUnitUtf8 = dataSet.rangeDisplayUnit.toUtf8();
+ dataSetJson.AddMember("XDisplayUnit",
+ rapidjson::Value(xDisplayUnitUtf8.constData(), allocator).Move(), allocator);
+ dataSetJson.AddMember("YDisplayUnit",
+ rapidjson::Value(yDisplayUnitUtf8.constData(), allocator).Move(), allocator);
+ dataSetJson.AddMember("ValueDisplayUnit",
+ rapidjson::Value(valueDisplayUnitUtf8.constData(), allocator).Move(), allocator);
+ dataSetJson.AddMember("RangeDisplayUnit",
+ rapidjson::Value(rangeDisplayUnitUtf8.constData(), allocator).Move(), allocator);
+ dataSetJson.AddMember("UseForCalculation", dataSet.useForCalculation, allocator);
+ dataSetJson.AddMember("ShowPoints", dataSet.showPoints, allocator);
+ dataSetJson.AddMember("ShowLabels", dataSet.showLabels, allocator);
+ dataSetJson.AddMember("Nugget", dataSet.nugget, allocator);
+ dataSetJson.AddMember("Sill", dataSet.sill, allocator);
+ dataSetJson.AddMember("Range", dataSet.range, allocator);
+ dataSetJson.AddMember("Model", dataSet.model, allocator);
+
+ rapidjson::Value pointsJson(rapidjson::kArrayType);
+ for(int pointIndex = 0; pointIndex < dataSet.points.size(); ++pointIndex) {
+ const nmPropertyInterpolationPointData& point = dataSet.points[pointIndex];
+ rapidjson::Value pointJson(rapidjson::kObjectType);
+ pointJson.AddMember("X", point.x, allocator);
+ pointJson.AddMember("Y", point.y, allocator);
+ pointJson.AddMember("Value", point.value, allocator);
+ pointsJson.PushBack(pointJson, allocator);
+ }
+ dataSetJson.AddMember("Points", pointsJson, allocator);
+ interpolationDataSetsJson.PushBack(dataSetJson, allocator);
+ }
+ doc.AddMember("PropertyInterpolationDataSets", interpolationDataSetsJson, allocator);
+
// 序列化 "Reservoir"
if(m_reservoirData) {
rapidjson::Value reservoirJson(rapidjson::kObjectType);
diff --git a/Src/nmNum/nmData/nmDataJsonTools.cpp b/Src/nmNum/nmData/nmDataJsonTools.cpp
index cadf570..36ba197 100644
--- a/Src/nmNum/nmData/nmDataJsonTools.cpp
+++ b/Src/nmNum/nmData/nmDataJsonTools.cpp
@@ -7,7 +7,6 @@
// RapidJSON 内部使用 char*,这里需要转换为 std::string
#include
#include
-#include
#include
#include "rapidjson/document.h"
@@ -211,39 +210,34 @@ bool nmDataJsonTools::WriteDomToFile(const rapidjson::Document& doc, const QStri
rapidjson::PrettyWriter writer(buffer); // 使用 PrettyWriter 进行美化输出
doc.Accept(writer);
- // 将字符串写入文件
+ /* RapidJSON输出为UTF-8字节,直接写入可避免中文被本地编码再次转换 */
QFile file(filePath);
- if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
+ if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
qDebug() << "Error: Could not open file for writing:" << filePath;
return false;
}
- QTextStream out(&file);
- out << buffer.GetString();
+ const qint64 bufferSize = static_cast(buffer.GetSize());
+ const qint64 writtenSize = file.write(buffer.GetString(), bufferSize);
file.close();
- return true;
+ return writtenSize == bufferSize;
}
// 从文件读取 JSON 并解析到 RapidJSON Document
bool nmDataJsonTools::ReadDomFromFile(const QString& filePath, rapidjson::Document& doc)
{
QFile file(filePath);
- if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ if (!file.open(QIODevice::ReadOnly)) {
qDebug() << "Error: Could not open file for reading:" << filePath;
return false;
}
- QTextStream in(&file);
- QString jsonString = in.readAll();
+ const QByteArray jsonData = file.readAll();
file.close();
- // 将 QString 转换为 std::string
- QByteArray byteArray = jsonString.toUtf8();
- std::string stdJsonString = byteArray.constData();
-
- // 解析 JSON 字符串到 RapidJSON Document
- doc.Parse(stdJsonString.c_str());
+ /* 文件内容保持RapidJSON所需的UTF-8编码 */
+ doc.Parse(jsonData.constData());
if (doc.HasParseError()) {
qDebug() << "Error parsing JSON from file:" << filePath << "Error:" << doc.GetParseError();
@@ -251,4 +245,4 @@ bool nmDataJsonTools::ReadDomFromFile(const QString& filePath, rapidjson::Docume
}
return true;
-}
\ No newline at end of file
+}
diff --git a/Src/nmNum/nmPlot/nmGuiPlot.cpp b/Src/nmNum/nmPlot/nmGuiPlot.cpp
index dd41ffe..2e39630 100644
--- a/Src/nmNum/nmPlot/nmGuiPlot.cpp
+++ b/Src/nmNum/nmPlot/nmGuiPlot.cpp
@@ -167,6 +167,14 @@ bool nmGuiPlot::runAction(QString sAction)
return m_pCmdHelper->runAction(sAction);
}
+void nmGuiPlot::cancelActiveTools()
+{
+ nmGuiPlotCmdHelper* helper = dynamic_cast(m_pCmdHelper);
+ if(helper != NULL) {
+ helper->cancelActiveTools();
+ }
+}
+
void nmGuiPlot::initDefultGeoObj()
{
diff --git a/Src/nmNum/nmPlot/nmGuiPlotCmdHelper.cpp b/Src/nmNum/nmPlot/nmGuiPlotCmdHelper.cpp
index 03d6d16..836329e 100644
--- a/Src/nmNum/nmPlot/nmGuiPlotCmdHelper.cpp
+++ b/Src/nmNum/nmPlot/nmGuiPlotCmdHelper.cpp
@@ -161,6 +161,7 @@ bool nmGuiPlotCmdHelper::runAction(QString sAction) {
pPlot->appendTools(pObjTool);
connect(pObjTool, SIGNAL(sigPtsFinished(QVector&)), \
this, SLOT(slotObjPtsFinished(QVector&)));
+ m_activeTools.insert(pObjTool->getNOT(), pObjTool);
return true;
} else if (_isSame(sAction, "nmInsertObjPointWell")) {
nmObjToolBase* pObjTool = new nmObjPointWellTool();
@@ -169,6 +170,7 @@ bool nmGuiPlotCmdHelper::runAction(QString sAction) {
pPlot->appendTools(pObjTool);
connect(pObjTool, SIGNAL(sigPtsFinished(QVector&)), \
this, SLOT(slotObjPtsFinished(QVector&)));
+ m_activeTools.insert(pObjTool->getNOT(), pObjTool);
return true;
} else if (_isSame(sAction, "nmInsertObjLine")) {
nmObjToolBase* pObjTool = new nmObjLineTool();
@@ -176,6 +178,7 @@ bool nmGuiPlotCmdHelper::runAction(QString sAction) {
pPlot->appendTools(pObjTool);
connect(pObjTool, SIGNAL(sigPtsFinished(QVector&)), \
this, SLOT(slotObjPtsFinished(QVector&)));
+ m_activeTools.insert(pObjTool->getNOT(), pObjTool);
return true;
} else if (_isSame(sAction, "nmInsertObjPolygon")) {
nmObjToolBase* pObjTool = new nmObjPolygonTool();
@@ -183,6 +186,7 @@ bool nmGuiPlotCmdHelper::runAction(QString sAction) {
pPlot->appendTools(pObjTool);
connect(pObjTool, SIGNAL(sigPtsFinished(QVector&)), \
this, SLOT(slotObjPtsFinished(QVector&)));
+ m_activeTools.insert(pObjTool->getNOT(), pObjTool);
return true;
} else if (_isSame(sAction, "nmInsertObjPolygonOutline")) {
nmObjToolBase* pObjTool = new nmObjPolygonOutlineTool();
@@ -190,6 +194,7 @@ bool nmGuiPlotCmdHelper::runAction(QString sAction) {
pPlot->appendTools(pObjTool);
connect(pObjTool, SIGNAL(sigPtsFinished(QVector&)), \
this, SLOT(slotObjPtsFinished(QVector&)));
+ m_activeTools.insert(pObjTool->getNOT(), pObjTool);
return true;
} else if (_isSame(sAction, "nmInsertObjRect")) {
nmObjToolBase* pObjTool = new nmObjRectTool(); //矩形对象工具类
@@ -197,6 +202,7 @@ bool nmGuiPlotCmdHelper::runAction(QString sAction) {
pPlot->appendTools(pObjTool);
connect(pObjTool, SIGNAL(sigPtsFinished(QVector&)), \
this, SLOT(slotObjPtsFinished(QVector&)));
+ m_activeTools.insert(pObjTool->getNOT(), pObjTool);
return true;
} else if (_isSame(sAction, "nmInsertObjRectOutline")) {
nmObjToolBase* pObjTool = new nmObjRectOutlineTool(); //矩形边界工具类
@@ -204,6 +210,7 @@ bool nmGuiPlotCmdHelper::runAction(QString sAction) {
pPlot->appendTools(pObjTool);
connect(pObjTool, SIGNAL(sigPtsFinished(QVector&)), \
this, SLOT(slotObjPtsFinished(QVector&)));
+ m_activeTools.insert(pObjTool->getNOT(), pObjTool);
return true;
} else if (_isSame(sAction, "nmInsertObjRound")) {
nmObjToolBase* pObjTool = new nmObjRoundTool(); //圆形对象工具类
@@ -211,6 +218,7 @@ bool nmGuiPlotCmdHelper::runAction(QString sAction) {
pPlot->appendTools(pObjTool);
connect(pObjTool, SIGNAL(sigPtsFinished(QVector&)), \
this, SLOT(slotObjPtsFinished(QVector&)));
+ m_activeTools.insert(pObjTool->getNOT(), pObjTool);
return true;
} else if (_isSame(sAction, "nmInsertObjRoundOutline")) {
nmObjToolBase* pObjTool = new nmObjRoundOutlineTool(); //圆形边界工具类
@@ -218,6 +226,7 @@ bool nmGuiPlotCmdHelper::runAction(QString sAction) {
pPlot->appendTools(pObjTool);
connect(pObjTool, SIGNAL(sigPtsFinished(QVector&)), \
this, SLOT(slotObjPtsFinished(QVector&)));
+ m_activeTools.insert(pObjTool->getNOT(), pObjTool);
return true;
} else if (_isSame(sAction, "nmInsertObjLineCrack")) {
nmObjToolBase* pObjTool = new nmObjLineCrackTool();
@@ -298,6 +307,21 @@ bool nmGuiPlotCmdHelper::runAction(QString sAction) {
return iGuiPlotCmdHelper::runAction(sAction);
}
+void nmGuiPlotCmdHelper::cancelActiveTools()
+{
+ nmGuiPlot* pWxPlot = dynamic_cast(m_pGuiPlot);
+ if(pWxPlot == nullptr || pWxPlot->m_pPlot == nullptr ||
+ pWxPlot->m_pPlotView == nullptr) {
+ return;
+ }
+
+ foreach (nmObjToolBase* activeTool, m_activeTools.values()) {
+ pWxPlot->m_pPlot->removeTools(activeTool);
+ }
+ m_activeTools.clear();
+ finalWithAcm(true, true);
+}
+
void nmGuiPlotCmdHelper::slotObjPtsFinished(QVector& vec) {
nmObjToolBase* pTool = dynamic_cast(sender());
if (NULL == pTool) {
diff --git a/Src/nmNum/nmSubWnd/nmSubWndMain.cpp b/Src/nmNum/nmSubWnd/nmSubWndMain.cpp
index f207478..1f2b236 100644
--- a/Src/nmNum/nmSubWnd/nmSubWndMain.cpp
+++ b/Src/nmNum/nmSubWnd/nmSubWndMain.cpp
@@ -57,6 +57,7 @@
#include "nmWxWellLayerDlg.h"
#include "nmWxGeometryLayerDlg.h"
#include "nmWxReservoirPropertiesDlg.h"
+#include "nmWxPropertyInterpolationDlg.h"
#include "nmWxPostprocessingAnimationWidget.h"
#include "nmWxGeoRefDlg.h"
@@ -512,6 +513,13 @@ bool nmSubWndMain::runCmdBy(QString sName, QString sID)
}
this->drawPointerPos();
return true;
+
+ case 5126:
+ if(isDialogCmdOpened(5126)) {
+ return true;
+ }
+ this->showPropertyInterpolationDialog();
+ return true;
}
if(_isSame(s, "RunGrid")) {
@@ -557,6 +565,7 @@ bool nmSubWndMain::checkCmdEnable(bool &b, \
if(sName == "NmMap" || sName == "NmUnlocked" || sName == "NmGeometry" ||
sName == "NmProperties" || sName == "NmDFN" || sName == "NmCaculation" ||
sName == "NmBack" || sName == "NmResult" || sName == "NmGrid" ||
+ sName == "NmInterpolation" ||
sName == "NmShow" || sName == "NmPrintPreview" || sName == "NmPrint" ||
sName == "VisibleAnalBasic" || sName == "VisibleAnalPVT" || sName == "VisibleAnalDiff" ||
sName == "VisibleAnalPseu" || sName == "nmFitModel" || sName == "NmAnalChange") {
@@ -1435,6 +1444,21 @@ QWidget* nmSubWndMain::showPointerPosDialog()
return pointerPosDlg;
}
+QWidget* nmSubWndMain::showPropertyInterpolationDialog()
+{
+ nmWxPropertyInterpolationDlg* interpolationDlg = new nmWxPropertyInterpolationDlg(
+ m_pWxPlot, nmDataAnalyzeManager::getCurrentInstance(), this);
+ markDialogCmdOpened(5126);
+ interpolationDlg->setObjectName("nmPropertyInterpolationDialog");
+ // 关闭窗口时自动释放,并恢复菜单命令的可用状态
+ interpolationDlg->setAttribute(Qt::WA_DeleteOnClose, true);
+ bindDialogCmdDestroyed(interpolationDlg, 5126);
+ interpolationDlg->show();
+ interpolationDlg->raise();
+ interpolationDlg->activateWindow();
+ return interpolationDlg;
+}
+
void nmSubWndMain::generationMesh()
{
// // TODO,还不支持原型边界
diff --git a/Src/nmNum/nmSubWxs/nmWxPropertyInterpolationDlg.cpp b/Src/nmNum/nmSubWxs/nmWxPropertyInterpolationDlg.cpp
new file mode 100644
index 0000000..7c8ccf2
--- /dev/null
+++ b/Src/nmNum/nmSubWxs/nmWxPropertyInterpolationDlg.cpp
@@ -0,0 +1,1955 @@
+#include "nmWxPropertyInterpolationDlg.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "nmCalculationUtils.h"
+#include "nmDataOutline.h"
+#include "nmGuiPlot.h"
+#include "nmObjPoint.h"
+#include "nmObjPointWell.h"
+#include "nmWxPropertyInterpolationPreviewDlg.h"
+#include "iUnitGroup.h"
+#include "iUnitHelper.h"
+#include "tCurvePlotView.h"
+#include "ZxDataWell.h"
+#include "ZxObjText.h"
+#include "ZxPlot.h"
+
+namespace
+{
+// 表格第0行保留给单位,实际测点从第1行开始.
+const int POINT_UNIT_ROW = 0;
+const int FIRST_POINT_ROW = 1;
+// 坐标和厚度以m保存,渗透率以D保存但默认使用mD显示.
+const char* LENGTH_BASE_UNIT = "m";
+const char* PERMEABILITY_BASE_UNIT = "D";
+const char* PERMEABILITY_DISPLAY_UNIT = "mD";
+
+// 使用独立翻译上下文,便于统一维护对话框文本.
+QString interpolationText(const char* sourceText)
+{
+ return QCoreApplication::translate("nmWxPropertyInterpolationDlg", sourceText);
+}
+
+// 创建统一格式的非负数值输入框.
+QDoubleSpinBox* createNumberSpinBox(QWidget* parent, double value)
+{
+ QDoubleSpinBox* spinBox = new QDoubleSpinBox(parent);
+ spinBox->setRange(0.0, 1.0e12);
+ spinBox->setDecimals(6);
+ spinBox->setValue(value);
+ spinBox->setButtonSymbols(QAbstractSpinBox::NoButtons);
+ return spinBox;
+}
+
+QString propertyBaseUnit(const QString& property)
+{
+ // 孔隙度为无量纲量,返回空单位后界面会禁用对应单位下拉框.
+ if(property == "k") {
+ return PERMEABILITY_BASE_UNIT;
+ }
+ if(property == "h") {
+ return LENGTH_BASE_UNIT;
+ }
+ return QString();
+}
+
+QString defaultPropertyDisplayUnit(const QString& property)
+{
+ // 渗透率采用工程中常用的mD显示,其余属性默认显示基准单位.
+ if(property == "k") {
+ return PERMEABILITY_DISPLAY_UNIT;
+ }
+ return propertyBaseUnit(property);
+}
+
+QString unitGroupLookupUnit(const QString& unit)
+{
+ // D与时间单位d仅大小写不同,使用唯一的mD定位渗透率单位组.
+ return unit == PERMEABILITY_BASE_UNIT ?
+ QString(PERMEABILITY_DISPLAY_UNIT) : unit;
+}
+
+bool convertUnitValue(double sourceValue,
+ const QString& sourceUnit,
+ const QString& destinationUnit,
+ double& destinationValue)
+{
+ if(sourceUnit == destinationUnit ||
+ (sourceUnit.isEmpty() && destinationUnit.isEmpty())) {
+ destinationValue = sourceValue;
+ return true;
+ }
+ if(sourceUnit.isEmpty() || destinationUnit.isEmpty()) {
+ return false;
+ }
+
+ // 复用框架单位表完成换算,不在插值模块中维护独立换算系数.
+ iUnitGroup* unitGroup = iUnitHelper::getUnitGroupByUnit(
+ unitGroupLookupUnit(sourceUnit));
+ if(unitGroup == NULL || unitGroup->indexOf(destinationUnit) < 0) {
+ return false;
+ }
+
+ int digit = 6;
+ return unitGroup->convert(sourceUnit, sourceValue,
+ destinationUnit, destinationValue, digit);
+}
+
+double convertedUnitValue(double sourceValue,
+ const QString& sourceUnit,
+ const QString& destinationUnit)
+{
+ double destinationValue = sourceValue;
+ convertUnitValue(sourceValue, sourceUnit,
+ destinationUnit, destinationValue);
+ return destinationValue;
+}
+
+QString displayValueText(double value)
+{
+ // 表格使用较高有效位数,减少多次显示和回写造成的精度损失.
+ return QString::number(value, 'g', 15);
+}
+
+void populateUnitCombo(QComboBox* comboBox,
+ const QString& baseUnit,
+ const QString& selectedUnit)
+{
+ if(comboBox == NULL) {
+ return;
+ }
+
+ // 单位列表从全局单位表加载,屏蔽信号可避免初始化过程反向修改数据.
+ bool oldBlock = comboBox->blockSignals(true);
+ comboBox->clear();
+ if(baseUnit.isEmpty()) {
+ comboBox->addItem(QString());
+ comboBox->setCurrentIndex(0);
+ comboBox->setEnabled(false);
+ comboBox->blockSignals(oldBlock);
+ return;
+ }
+
+ const QString lookupUnit = unitGroupLookupUnit(baseUnit);
+ QStringList units;
+ iUnitGroup* unitGroup = iUnitHelper::getUnitGroupByUnit(lookupUnit);
+ if(unitGroup != NULL) {
+ units = unitGroup->getAllUnitNames();
+ }
+ if(units.isEmpty()) {
+ units.append(baseUnit);
+ }
+ comboBox->addItems(units);
+
+ int selectedIndex = comboBox->findText(selectedUnit);
+ if(selectedIndex < 0) {
+ selectedIndex = comboBox->findText(lookupUnit);
+ }
+ if(selectedIndex < 0) {
+ selectedIndex = comboBox->findText(baseUnit);
+ }
+ comboBox->setCurrentIndex(selectedIndex < 0 ? 0 : selectedIndex);
+ comboBox->setEnabled(true);
+ comboBox->blockSignals(oldBlock);
+}
+
+void setTableUnitComboStyle(QComboBox* comboBox)
+{
+ if(comboBox == NULL) {
+ return;
+ }
+
+ // 仅借用可编辑模式调整文字对齐,输入区域仍设置为只读.
+ comboBox->setEditable(true);
+ comboBox->lineEdit()->setAlignment(Qt::AlignCenter);
+ comboBox->lineEdit()->setReadOnly(true);
+ comboBox->setStyleSheet(
+ "QComboBox { border: none; background: transparent; padding-left: 4px; }"
+ "QComboBox::drop-down { border: none; }");
+}
+
+// 插值测点使用独立的小方块标记,避免与井图元混淆.
+class PropertyInterpolationMarker : public nmObjPoint
+{
+public:
+ PropertyInterpolationMarker(const QString& name,
+ ZxSubAxisX* axisX,
+ ZxSubAxisY* axisY)
+ : nmObjPoint(name, axisX, axisY)
+ {
+ setDotRadius(1.0);
+ }
+
+ virtual bool drawWellPos(QPainter* painter, QPointF point) override
+ {
+ if(painter == NULL) {
+ return false;
+ }
+
+ const QTransform transform = painter->combinedTransform();
+ qreal scaleX = qAbs(transform.m11());
+ qreal scaleY = qAbs(transform.m22());
+
+ if(scaleX < 0.0001) {
+ scaleX = 1.0;
+ }
+
+ if(scaleY < 0.0001) {
+ scaleY = 1.0;
+ }
+
+ const qreal halfPixelSize = 3.0;
+ QRectF markerRect(point.x() - halfPixelSize / scaleX,
+ point.y() - halfPixelSize / scaleY,
+ halfPixelSize * 2.0 / scaleX,
+ halfPixelSize * 2.0 / scaleY);
+
+ painter->save();
+ QPen pen(QColor(0, 25, 100));
+ pen.setWidthF(1.0);
+ pen.setCosmetic(true);
+ painter->setPen(pen);
+ painter->setBrush(QColor(0, 70, 200));
+ painter->drawRect(markerRect);
+ painter->restore();
+ return true;
+ }
+};
+
+void setMarkerLabel(nmObjPoint* marker, const QString& text)
+{
+ if(marker == NULL || marker->getChildren().isEmpty()) {
+ return;
+ }
+
+ ZxObjText* label = dynamic_cast(marker->at(0));
+ if(label != NULL) {
+ label->setText(text);
+ label->setTextColor(QColor(30, 30, 30));
+ }
+}
+
+// 将储层边界转换成预览裁剪使用的多边形,并计算规则采样范围.
+bool createPreviewOutline(nmDataOutline* outline,
+ QVector& outlinePoints,
+ QRectF& bounds)
+{
+ outlinePoints.clear();
+ bounds = QRectF();
+ if(outline == NULL) {
+ return false;
+ }
+
+ if(outline->getOutlineType() == NM_Round_Outline_Type) {
+ // 圆形边界离散成多边形,便于预览窗口统一裁剪.
+ const QPointF center = outline->getCenter();
+ const double radius = outline->getRadius();
+ if(radius <= 0.0) {
+ return false;
+ }
+
+ const int segmentCount = 72;
+ const double fullCircle = 6.28318530717958647692;
+ for(int i = 0; i < segmentCount; ++i) {
+ const double angle = fullCircle * i / segmentCount;
+ outlinePoints.append(QPointF(center.x() + radius * qCos(angle),
+ center.y() + radius * qSin(angle)));
+ }
+ } else {
+ outlinePoints = outline->getOutlinePoints();
+ if(outlinePoints.size() > 3 &&
+ outlinePoints.first() == outlinePoints.last()) {
+ outlinePoints.remove(outlinePoints.size() - 1);
+ }
+ }
+
+ if(outlinePoints.size() < 3) {
+ return false;
+ }
+
+ bounds = QPolygonF(outlinePoints).boundingRect().normalized();
+ return bounds.width() > 0.0 && bounds.height() > 0.0;
+}
+}
+
+nmWxPropertyInterpolationDlg::nmWxPropertyInterpolationDlg(
+ nmGuiPlot* plot,
+ nmDataAnalyzeManager* dataManager,
+ QWidget* parent)
+ : iDlgBase(parent),
+ m_pPlot(plot),
+ m_pDataManager(dataManager),
+ m_pDataSetCombo(NULL),
+ m_pAddDataSetButton(NULL),
+ m_pDeleteDataSetButton(NULL),
+ m_nCurrentDataSetIndex(-1),
+ m_nNextPointId(0),
+ m_bUpdatingUi(true),
+ m_pPropertyCombo(NULL),
+ m_pNameEdit(NULL),
+ m_pNewValueSpin(NULL),
+ m_pNewValueUnitCombo(NULL),
+ m_pMapPickButton(NULL),
+ m_pPointTable(NULL),
+ m_pXUnitCombo(NULL),
+ m_pYUnitCombo(NULL),
+ m_pValueUnitCombo(NULL),
+ m_pDeletePointButton(NULL),
+ m_pClearPointsButton(NULL),
+ m_pShowPointsCheck(NULL),
+ m_pShowLabelsCheck(NULL),
+ m_pNuggetSpin(NULL),
+ m_pSillSpin(NULL),
+ m_pRangeSpin(NULL),
+ m_pRangeUnitCombo(NULL),
+ m_pModelCombo(NULL),
+ m_pUseKCheck(NULL),
+ m_pKCalculationDataSetCombo(NULL),
+ m_pUsePhiCheck(NULL),
+ m_pPhiCalculationDataSetCombo(NULL),
+ m_pUseHCheck(NULL),
+ m_pHCalculationDataSetCombo(NULL),
+ m_pPreviewButton(NULL),
+ m_pPreviewDialog(NULL),
+ m_pPreviewRefreshTimer(NULL)
+{
+ setWindowTitle(interpolationText("Property Interpolation"));
+ setWindowModality(Qt::NonModal);
+ setModal(false);
+
+ // 合并连续编辑触发的刷新,避免每次数值变化都立即重新插值.
+ m_pPreviewRefreshTimer = new QTimer(this);
+ m_pPreviewRefreshTimer->setSingleShot(true);
+ m_pPreviewRefreshTimer->setInterval(200);
+ connect(m_pPreviewRefreshTimer, SIGNAL(timeout()),
+ this, SLOT(refreshPreview()));
+
+ initInterpolationUI();
+ initializeDataSets();
+
+ if(qApp != NULL) {
+ qApp->installEventFilter(this);
+ }
+}
+
+nmWxPropertyInterpolationDlg::~nmWxPropertyInterpolationDlg()
+{
+ if(qApp != NULL) {
+ qApp->removeEventFilter(this);
+ }
+
+ onMapPickToggled(false);
+ saveCurrentDataSet();
+ syncDataSetsToManager(false);
+ removeAllMarkers();
+}
+
+void nmWxPropertyInterpolationDlg::initInterpolationUI()
+{
+ const int topControlWidth = 350;
+ const int compactComboWidth = 200;
+
+ QVBoxLayout* mainLayout = new QVBoxLayout(this);
+ mainLayout->setContentsMargins(12, 10, 12, 10);
+ mainLayout->setSpacing(8);
+
+ // 数据组、名称和属性共用一个表单,保证三行标签及输入控件对齐.
+ QFormLayout* dataSetLayout = new QFormLayout;
+ dataSetLayout->setContentsMargins(0, 0, 0, 0);
+ dataSetLayout->setHorizontalSpacing(8);
+ dataSetLayout->setVerticalSpacing(6);
+ dataSetLayout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow);
+
+ QWidget* dataSetSelectWidget = new QWidget(this);
+ dataSetSelectWidget->setMaximumWidth(topControlWidth);
+ QHBoxLayout* dataSetSelectLayout = new QHBoxLayout(dataSetSelectWidget);
+ dataSetSelectLayout->setContentsMargins(0, 0, 0, 0);
+ dataSetSelectLayout->setSpacing(6);
+ m_pDataSetCombo = new QComboBox(dataSetSelectWidget);
+ dataSetSelectLayout->addWidget(m_pDataSetCombo, 1);
+
+ QString iconDir = QCoreApplication::applicationDirPath();
+ iconDir = iconDir.section('/', 0, -2) + "/Res/Icon/";
+
+ // 数据组操作按钮使用独立边框,便于识别可点击区域.
+ const QString dataSetButtonStyle =
+ "QPushButton {"
+ " border: 1px solid #aeb5bd;"
+ " border-radius: 3px;"
+ " background-color: #ffffff;"
+ " padding: 0px;"
+ "}"
+ "QPushButton:hover {"
+ " border-color: #6d9fc7;"
+ " background-color: #f5f9fc;"
+ "}"
+ "QPushButton:pressed {"
+ " background-color: #e8f1f8;"
+ "}"
+ "QPushButton:disabled {"
+ " border-color: #d6d9dc;"
+ " background-color: #f5f5f5;"
+ "}";
+
+ m_pAddDataSetButton = new QPushButton(dataSetSelectWidget);
+ m_pAddDataSetButton->setIcon(QIcon(iconDir + "Add.png"));
+ m_pAddDataSetButton->setIconSize(QSize(20, 20));
+ m_pAddDataSetButton->setFixedSize(34, 30);
+ m_pAddDataSetButton->setStyleSheet(dataSetButtonStyle);
+ m_pAddDataSetButton->setToolTip(interpolationText("Add dataset"));
+ dataSetSelectLayout->addWidget(m_pAddDataSetButton);
+
+ m_pDeleteDataSetButton = new QPushButton(dataSetSelectWidget);
+ m_pDeleteDataSetButton->setIcon(QIcon(iconDir + "NmDelete.png"));
+ m_pDeleteDataSetButton->setIconSize(QSize(20, 20));
+ m_pDeleteDataSetButton->setFixedSize(34, 30);
+ m_pDeleteDataSetButton->setStyleSheet(dataSetButtonStyle);
+ m_pDeleteDataSetButton->setToolTip(interpolationText("Delete dataset"));
+ dataSetSelectLayout->addWidget(m_pDeleteDataSetButton);
+ dataSetLayout->addRow(interpolationText("Dataset:"), dataSetSelectWidget);
+
+ m_pNameEdit = new QLineEdit(this);
+ m_pNameEdit->setMaximumWidth(topControlWidth);
+ dataSetLayout->addRow(interpolationText("Name:"), m_pNameEdit);
+
+ m_pPropertyCombo = new QComboBox(this);
+ m_pPropertyCombo->setMaximumWidth(topControlWidth);
+ m_pPropertyCombo->addItem(interpolationText("Permeability k"), QString("k"));
+ m_pPropertyCombo->addItem(interpolationText("Porosity phi"), QString("phi"));
+ m_pPropertyCombo->addItem(interpolationText("Reservoir thickness h"), QString("h"));
+ dataSetLayout->addRow(interpolationText("Property:"), m_pPropertyCombo);
+ mainLayout->addLayout(dataSetLayout);
+
+ // 测点数据录入区域.
+ QGroupBox* pointGroup = new QGroupBox(interpolationText("Measurement Points"), this);
+ QVBoxLayout* pointLayout = new QVBoxLayout(pointGroup);
+ pointLayout->setContentsMargins(10, 8, 10, 10);
+ pointLayout->setSpacing(6);
+
+ QHBoxLayout* newPointLayout = new QHBoxLayout;
+ newPointLayout->setSpacing(6);
+ newPointLayout->addWidget(new QLabel(interpolationText("New value:"), pointGroup));
+ m_pNewValueSpin = createNumberSpinBox(pointGroup, 0.0);
+ newPointLayout->addWidget(m_pNewValueSpin, 1);
+ m_pNewValueUnitCombo = new QComboBox(pointGroup);
+ m_pNewValueUnitCombo->setFixedWidth(80);
+ populateUnitCombo(m_pNewValueUnitCombo,
+ PERMEABILITY_BASE_UNIT, PERMEABILITY_DISPLAY_UNIT);
+ newPointLayout->addWidget(m_pNewValueUnitCombo);
+ m_pMapPickButton = new QPushButton(interpolationText("Select on Map"), pointGroup);
+ m_pMapPickButton->setIcon(QIcon(iconDir + "AddPoint.png"));
+ m_pMapPickButton->setIconSize(QSize(16, 16));
+ m_pMapPickButton->setMinimumWidth(100);
+ m_pMapPickButton->setCheckable(true);
+ m_pMapPickButton->setEnabled(!m_pPlot.isNull() &&
+ m_pPlot->m_pPlotView != NULL &&
+ m_pPlot->m_pPlot != NULL);
+ newPointLayout->addWidget(m_pMapPickButton);
+ pointLayout->addLayout(newPointLayout);
+
+ m_pPointTable = new QTableWidget(1, 3, pointGroup);
+ QStringList headers;
+ headers << interpolationText("X") << interpolationText("Y") << interpolationText("Value");
+ m_pPointTable->setHorizontalHeaderLabels(headers);
+ m_pPointTable->verticalHeader()->setVisible(true);
+ m_pPointTable->verticalHeader()->setFixedWidth(36);
+ m_pPointTable->verticalHeader()->setDefaultAlignment(Qt::AlignCenter);
+ // 第0行为单位选择,不占用测点序号.
+ m_pPointTable->setVerticalHeaderItem(
+ POINT_UNIT_ROW, new QTableWidgetItem(QString()));
+ m_pPointTable->horizontalHeader()->setResizeMode(QHeaderView::Stretch);
+ m_pPointTable->setSelectionBehavior(QAbstractItemView::SelectRows);
+ m_pPointTable->setSelectionMode(QAbstractItemView::SingleSelection);
+ m_pPointTable->setAlternatingRowColors(true);
+ m_pPointTable->setMinimumHeight(170);
+ m_pPointTable->setRowHeight(POINT_UNIT_ROW, 24);
+
+ // 第0行固定显示各列单位,数据行从第1行开始.
+ m_pXUnitCombo = new QComboBox(m_pPointTable);
+ m_pYUnitCombo = new QComboBox(m_pPointTable);
+ m_pValueUnitCombo = new QComboBox(m_pPointTable);
+ setTableUnitComboStyle(m_pXUnitCombo);
+ setTableUnitComboStyle(m_pYUnitCombo);
+ setTableUnitComboStyle(m_pValueUnitCombo);
+ populateUnitCombo(m_pXUnitCombo, LENGTH_BASE_UNIT, LENGTH_BASE_UNIT);
+ populateUnitCombo(m_pYUnitCombo, LENGTH_BASE_UNIT, LENGTH_BASE_UNIT);
+ populateUnitCombo(m_pValueUnitCombo,
+ PERMEABILITY_BASE_UNIT, PERMEABILITY_DISPLAY_UNIT);
+ m_pPointTable->setCellWidget(POINT_UNIT_ROW, 0, m_pXUnitCombo);
+ m_pPointTable->setCellWidget(POINT_UNIT_ROW, 1, m_pYUnitCombo);
+ m_pPointTable->setCellWidget(POINT_UNIT_ROW, 2, m_pValueUnitCombo);
+ pointLayout->addWidget(m_pPointTable, 1);
+
+ // 显示选项放在左侧,当前测点操作放在右侧,减少分散的按钮行.
+ QHBoxLayout* pointButtonLayout = new QHBoxLayout;
+ pointButtonLayout->setSpacing(8);
+ m_pShowPointsCheck = new QCheckBox(interpolationText("Show measurement points"), pointGroup);
+ m_pShowPointsCheck->setChecked(true);
+ pointButtonLayout->addWidget(m_pShowPointsCheck);
+ m_pShowLabelsCheck = new QCheckBox(interpolationText("Show labels"), pointGroup);
+ m_pShowLabelsCheck->setChecked(true);
+ pointButtonLayout->addWidget(m_pShowLabelsCheck);
+ pointButtonLayout->addStretch();
+ m_pDeletePointButton = new QPushButton(interpolationText("Delete Selected"), pointGroup);
+ m_pDeletePointButton->setMinimumWidth(84);
+ m_pDeletePointButton->setEnabled(false);
+ pointButtonLayout->addWidget(m_pDeletePointButton);
+ m_pClearPointsButton = new QPushButton(interpolationText("Clear"), pointGroup);
+ m_pClearPointsButton->setMinimumWidth(72);
+ m_pClearPointsButton->setEnabled(false);
+ pointButtonLayout->addWidget(m_pClearPointsButton);
+ pointLayout->addLayout(pointButtonLayout);
+ mainLayout->addWidget(pointGroup, 1);
+
+ // Kriging参数采用两行双列布局,保持信息完整并压缩纵向空间.
+ QGroupBox* parameterGroup = new QGroupBox(interpolationText("Kriging Parameters"), this);
+ QGridLayout* parameterLayout = new QGridLayout(parameterGroup);
+ parameterLayout->setContentsMargins(10, 8, 10, 10);
+ parameterLayout->setHorizontalSpacing(8);
+ parameterLayout->setVerticalSpacing(6);
+ m_pNuggetSpin = createNumberSpinBox(parameterGroup, 0.01);
+ parameterLayout->addWidget(new QLabel(interpolationText("Nugget:"), parameterGroup), 0, 0);
+ parameterLayout->addWidget(m_pNuggetSpin, 0, 1);
+ m_pSillSpin = createNumberSpinBox(parameterGroup, 100.0);
+ parameterLayout->addWidget(new QLabel(interpolationText("Sill:"), parameterGroup), 0, 2);
+ parameterLayout->addWidget(m_pSillSpin, 0, 3);
+ QWidget* rangeWidget = new QWidget(parameterGroup);
+ QHBoxLayout* rangeLayout = new QHBoxLayout(rangeWidget);
+ rangeLayout->setContentsMargins(0, 0, 0, 0);
+ rangeLayout->setSpacing(6);
+ m_pRangeSpin = createNumberSpinBox(rangeWidget, 1000.0);
+ rangeLayout->addWidget(m_pRangeSpin, 1);
+ m_pRangeUnitCombo = new QComboBox(rangeWidget);
+ m_pRangeUnitCombo->setFixedWidth(72);
+ populateUnitCombo(m_pRangeUnitCombo, LENGTH_BASE_UNIT, LENGTH_BASE_UNIT);
+ rangeLayout->addWidget(m_pRangeUnitCombo);
+ parameterLayout->addWidget(new QLabel(interpolationText("Range:"), parameterGroup), 1, 0);
+ parameterLayout->addWidget(rangeWidget, 1, 1);
+ m_pModelCombo = new QComboBox(parameterGroup);
+ m_pModelCombo->setFixedWidth(compactComboWidth);
+ m_pModelCombo->addItem(interpolationText("Spherical (0)"), 0);
+ m_pModelCombo->addItem(interpolationText("Exponential (1)"), 1);
+ m_pModelCombo->addItem(interpolationText("Gaussian (2)"), 2);
+ parameterLayout->addWidget(new QLabel(interpolationText("Model:"), parameterGroup), 1, 2);
+ parameterLayout->addWidget(m_pModelCombo, 1, 3);
+ parameterLayout->setColumnStretch(1, 1);
+ parameterLayout->setColumnStretch(3, 1);
+ mainLayout->addWidget(parameterGroup);
+
+ // 分别指定正式求解时需要使用插值结果的属性和数据组.
+ QGroupBox* calculationGroup = new QGroupBox(
+ interpolationText("Use Interpolation in Solver"), this);
+ QGridLayout* calculationLayout = new QGridLayout(calculationGroup);
+ calculationLayout->setContentsMargins(10, 8, 10, 10);
+ calculationLayout->setHorizontalSpacing(8);
+ calculationLayout->setVerticalSpacing(6);
+ m_pUseKCheck = new QCheckBox(interpolationText("Permeability k"), calculationGroup);
+ m_pKCalculationDataSetCombo = new QComboBox(calculationGroup);
+ m_pKCalculationDataSetCombo->setFixedWidth(compactComboWidth);
+ calculationLayout->addWidget(m_pUseKCheck, 0, 0);
+ calculationLayout->addWidget(m_pKCalculationDataSetCombo, 0, 1);
+
+ m_pUsePhiCheck = new QCheckBox(interpolationText("Porosity phi"), calculationGroup);
+ m_pPhiCalculationDataSetCombo = new QComboBox(calculationGroup);
+ m_pPhiCalculationDataSetCombo->setFixedWidth(compactComboWidth);
+ calculationLayout->addWidget(m_pUsePhiCheck, 1, 0);
+ calculationLayout->addWidget(m_pPhiCalculationDataSetCombo, 1, 1);
+
+ m_pUseHCheck = new QCheckBox(interpolationText("Reservoir thickness h"), calculationGroup);
+ m_pHCalculationDataSetCombo = new QComboBox(calculationGroup);
+ m_pHCalculationDataSetCombo->setFixedWidth(compactComboWidth);
+ calculationLayout->addWidget(m_pUseHCheck, 2, 0);
+ calculationLayout->addWidget(m_pHCalculationDataSetCombo, 2, 1);
+ calculationLayout->setColumnMinimumWidth(1, compactComboWidth);
+ calculationLayout->setColumnStretch(2, 1);
+ mainLayout->addWidget(calculationGroup);
+
+ // 底部操作按钮.
+ QHBoxLayout* buttonLayout = new QHBoxLayout;
+ m_pPreviewButton = new QPushButton(interpolationText("Preview"), this);
+ m_pPreviewButton->setMinimumWidth(84);
+ m_pPreviewButton->setEnabled(false);
+ buttonLayout->addWidget(m_pPreviewButton);
+ buttonLayout->addStretch();
+ QPushButton* closeButton = new QPushButton(interpolationText("Close"), this);
+ closeButton->setMinimumWidth(84);
+ buttonLayout->addWidget(closeButton);
+ mainLayout->addLayout(buttonLayout);
+
+ connect(m_pDataSetCombo, SIGNAL(currentIndexChanged(int)),
+ this, SLOT(onDataSetChanged(int)));
+ connect(m_pAddDataSetButton, SIGNAL(clicked()), this, SLOT(onAddDataSet()));
+ connect(m_pDeleteDataSetButton, SIGNAL(clicked()), this, SLOT(onDeleteDataSet()));
+ connect(m_pNameEdit, SIGNAL(textChanged(QString)),
+ this, SLOT(onDataSetNameChanged(QString)));
+ connect(m_pPropertyCombo, SIGNAL(currentIndexChanged(int)),
+ this, SLOT(onCurrentDataSetPropertyChanged()));
+ connect(m_pNuggetSpin, SIGNAL(valueChanged(double)),
+ this, SLOT(onCurrentDataSetEdited()));
+ connect(m_pSillSpin, SIGNAL(valueChanged(double)),
+ this, SLOT(onCurrentDataSetEdited()));
+ connect(m_pRangeSpin, SIGNAL(valueChanged(double)),
+ this, SLOT(onCurrentDataSetEdited()));
+ connect(m_pXUnitCombo, SIGNAL(currentIndexChanged(const QString&)),
+ this, SLOT(onXDisplayUnitChanged(const QString&)));
+ connect(m_pYUnitCombo, SIGNAL(currentIndexChanged(const QString&)),
+ this, SLOT(onYDisplayUnitChanged(const QString&)));
+ connect(m_pNewValueUnitCombo, SIGNAL(currentIndexChanged(const QString&)),
+ this, SLOT(onValueDisplayUnitChanged(const QString&)));
+ connect(m_pValueUnitCombo, SIGNAL(currentIndexChanged(const QString&)),
+ this, SLOT(onValueDisplayUnitChanged(const QString&)));
+ connect(m_pRangeUnitCombo, SIGNAL(currentIndexChanged(const QString&)),
+ this, SLOT(onRangeDisplayUnitChanged(const QString&)));
+ connect(m_pModelCombo, SIGNAL(currentIndexChanged(int)),
+ this, SLOT(onCurrentDataSetEdited()));
+ connect(m_pMapPickButton, SIGNAL(toggled(bool)), this, SLOT(onMapPickToggled(bool)));
+ connect(m_pPointTable, SIGNAL(itemSelectionChanged()),
+ this, SLOT(onPointSelectionChanged()));
+ connect(m_pPointTable, SIGNAL(itemChanged(QTableWidgetItem*)),
+ this, SLOT(onPointItemChanged(QTableWidgetItem*)));
+ connect(m_pDeletePointButton, SIGNAL(clicked()), this, SLOT(onDeleteSelectedPoint()));
+ connect(m_pClearPointsButton, SIGNAL(clicked()), this, SLOT(onClearPoints()));
+ connect(m_pShowPointsCheck, SIGNAL(toggled(bool)), this, SLOT(onShowPointsToggled(bool)));
+ connect(m_pShowLabelsCheck, SIGNAL(toggled(bool)), this, SLOT(onShowLabelsToggled(bool)));
+ connect(m_pUseKCheck, SIGNAL(toggled(bool)),
+ this, SLOT(onCalculationSelectionChanged()));
+ connect(m_pKCalculationDataSetCombo, SIGNAL(currentIndexChanged(int)),
+ this, SLOT(onCalculationSelectionChanged()));
+ connect(m_pUsePhiCheck, SIGNAL(toggled(bool)),
+ this, SLOT(onCalculationSelectionChanged()));
+ connect(m_pPhiCalculationDataSetCombo, SIGNAL(currentIndexChanged(int)),
+ this, SLOT(onCalculationSelectionChanged()));
+ connect(m_pUseHCheck, SIGNAL(toggled(bool)),
+ this, SLOT(onCalculationSelectionChanged()));
+ connect(m_pHCalculationDataSetCombo, SIGNAL(currentIndexChanged(int)),
+ this, SLOT(onCalculationSelectionChanged()));
+ connect(m_pPreviewButton, SIGNAL(clicked()), this, SLOT(onPreview()));
+ connect(closeButton, SIGNAL(clicked()), this, SLOT(close()));
+}
+
+void nmWxPropertyInterpolationDlg::initializeDataSets()
+{
+ m_bUpdatingUi = true;
+
+ // 数据组允许为空,首次进入窗口时不自动创建默认数据组.
+ if(!m_pDataManager.isNull()) {
+ m_vecDataSets = m_pDataManager->getPropertyInterpolationDataSets();
+ }
+
+ bool dataChanged = false;
+ for(int i = 0; i < m_vecDataSets.size(); ++i) {
+ if(m_vecDataSets[i].name.isEmpty()) {
+ m_vecDataSets[i].name = nextDataSetName();
+ dataChanged = true;
+ }
+ }
+
+ m_vecMarkerNames.resize(m_vecDataSets.size());
+ // 测点标记不参与持久化,打开对话框时根据已保存测点重新创建.
+ createMarkersForAllDataSets();
+
+ bool oldBlock = m_pDataSetCombo->blockSignals(true);
+ m_pDataSetCombo->clear();
+ for(int i = 0; i < m_vecDataSets.size(); ++i) {
+ m_pDataSetCombo->addItem(m_vecDataSets[i].name);
+ }
+ const int initialIndex = m_vecDataSets.isEmpty() ? -1 : 0;
+ m_pDataSetCombo->setCurrentIndex(initialIndex);
+ m_pDataSetCombo->blockSignals(oldBlock);
+
+ m_nCurrentDataSetIndex = initialIndex;
+ loadDataSet(initialIndex);
+ m_bUpdatingUi = false;
+ updateDataSetButtons();
+ updateCalculationDataSetControls();
+
+ if(dataChanged) {
+ syncDataSetsToManager(false);
+ }
+}
+
+nmPropertyInterpolationDataSet nmWxPropertyInterpolationDlg::createDefaultDataSet()
+{
+ nmPropertyInterpolationDataSet dataSet;
+ dataSet.name = nextDataSetName();
+ dataSet.property = "k";
+ dataSet.showPoints = true;
+ dataSet.showLabels = true;
+ dataSet.nugget = 0.01;
+ dataSet.sill = 100.0;
+ dataSet.range = 1000.0;
+ dataSet.model = 0;
+ return dataSet;
+}
+
+QString nmWxPropertyInterpolationDlg::nextDataSetName()
+{
+ for(int number = 1; ; ++number) {
+ const QString name = interpolationText("Dataset #%1").arg(number);
+ bool exists = false;
+ for(int i = 0; i < m_vecDataSets.size(); ++i) {
+ if(m_vecDataSets[i].name == name) {
+ exists = true;
+ break;
+ }
+ }
+
+ if(!exists) {
+ return name;
+ }
+ }
+}
+
+void nmWxPropertyInterpolationDlg::loadDataSet(int index)
+{
+ if(index < 0 || index >= m_vecDataSets.size()) {
+ clearCurrentDataSet();
+ return;
+ }
+
+ // 切换数据组时批量刷新控件,避免控件信号被误判为用户修改.
+ bool wasUpdating = m_bUpdatingUi;
+ m_bUpdatingUi = true;
+ nmPropertyInterpolationDataSet& dataSet = m_vecDataSets[index];
+
+ m_pNameEdit->setText(dataSet.name);
+ int propertyIndex = m_pPropertyCombo->findData(dataSet.property);
+ m_pPropertyCombo->setCurrentIndex(propertyIndex < 0 ? 0 : propertyIndex);
+ updateUnitControls(dataSet);
+ m_pNewValueSpin->setValue(0.0);
+ m_pNuggetSpin->setValue(dataSet.nugget);
+ m_pSillSpin->setValue(dataSet.sill);
+ // Range在数据组中保存为m,加载时转换成当前选择的显示单位.
+ m_pRangeSpin->setValue(convertedUnitValue(
+ dataSet.range, LENGTH_BASE_UNIT,
+ m_pRangeUnitCombo->currentText()));
+ int modelIndex = m_pModelCombo->findData(dataSet.model);
+ m_pModelCombo->setCurrentIndex(modelIndex < 0 ? 0 : modelIndex);
+ m_pShowPointsCheck->setChecked(dataSet.showPoints);
+ m_pShowLabelsCheck->setChecked(dataSet.showLabels);
+
+ // 重建测点行时保留第0行单位控件,并阻止itemChanged反向修改数据.
+ bool oldTableBlock = m_pPointTable->blockSignals(true);
+ clearPointRows();
+ const QStringList markerNames = m_vecMarkerNames.value(index);
+ for(int i = 0; i < dataSet.points.size(); ++i) {
+ appendPointRow(dataSet.points[i], markerNames.value(i));
+ }
+ m_pPointTable->blockSignals(oldTableBlock);
+ updatePointDisplayValues();
+
+ clearTableSelection();
+ updatePointButtons();
+ updateCurrentMarkerVisibility();
+ m_bUpdatingUi = wasUpdating;
+ updateDataSetButtons();
+}
+
+void nmWxPropertyInterpolationDlg::clearCurrentDataSet()
+{
+ bool wasUpdating = m_bUpdatingUi;
+ m_bUpdatingUi = true;
+
+ if(m_pMapPickButton->isChecked()) {
+ m_pMapPickButton->setChecked(false);
+ }
+ m_pNameEdit->clear();
+ m_pPropertyCombo->setCurrentIndex(-1);
+ m_pNewValueSpin->setValue(0.0);
+ // 没有当前数据组时保留坐标基准单位,属性值单位置空并禁用.
+ populateUnitCombo(m_pXUnitCombo, LENGTH_BASE_UNIT, LENGTH_BASE_UNIT);
+ populateUnitCombo(m_pYUnitCombo, LENGTH_BASE_UNIT, LENGTH_BASE_UNIT);
+ populateUnitCombo(m_pNewValueUnitCombo, QString(), QString());
+ populateUnitCombo(m_pValueUnitCombo, QString(), QString());
+ populateUnitCombo(m_pRangeUnitCombo, LENGTH_BASE_UNIT, LENGTH_BASE_UNIT);
+ clearPointRows();
+ m_pShowPointsCheck->setChecked(false);
+ m_pShowLabelsCheck->setChecked(false);
+ m_pNuggetSpin->setValue(0.01);
+ m_pSillSpin->setValue(100.0);
+ m_pRangeSpin->setValue(1000.0);
+ m_pModelCombo->setCurrentIndex(-1);
+
+ clearTableSelection();
+ m_bUpdatingUi = wasUpdating;
+ updateDataSetButtons();
+}
+
+void nmWxPropertyInterpolationDlg::saveCurrentDataSet()
+{
+ if(m_nCurrentDataSetIndex < 0 ||
+ m_nCurrentDataSetIndex >= m_vecDataSets.size()) {
+ return;
+ }
+
+ nmPropertyInterpolationDataSet& dataSet = m_vecDataSets[m_nCurrentDataSetIndex];
+ dataSet.name = m_pNameEdit->text();
+ dataSet.property = m_pPropertyCombo->itemData(m_pPropertyCombo->currentIndex()).toString();
+ // 显示单位作为界面偏好保存,Range写回数据组前统一转换为米.
+ dataSet.xDisplayUnit = m_pXUnitCombo->currentText();
+ dataSet.yDisplayUnit = m_pYUnitCombo->currentText();
+ dataSet.valueDisplayUnit = propertyBaseUnit(dataSet.property).isEmpty() ?
+ QString() : m_pValueUnitCombo->currentText();
+ dataSet.rangeDisplayUnit = m_pRangeUnitCombo->currentText();
+ dataSet.nugget = m_pNuggetSpin->value();
+ dataSet.sill = m_pSillSpin->value();
+ dataSet.range = convertedUnitValue(
+ m_pRangeSpin->value(), dataSet.rangeDisplayUnit,
+ LENGTH_BASE_UNIT);
+ dataSet.model = m_pModelCombo->itemData(m_pModelCombo->currentIndex()).toInt();
+ dataSet.showPoints = m_pShowPointsCheck->isChecked();
+ dataSet.showLabels = m_pShowLabelsCheck->isChecked();
+
+}
+
+void nmWxPropertyInterpolationDlg::updateUnitControls(
+ nmPropertyInterpolationDataSet& dataSet)
+{
+ populateUnitCombo(m_pXUnitCombo, LENGTH_BASE_UNIT,
+ dataSet.xDisplayUnit);
+ populateUnitCombo(m_pYUnitCombo, LENGTH_BASE_UNIT,
+ dataSet.yDisplayUnit);
+
+ const QString valueBaseUnit = propertyBaseUnit(dataSet.property);
+ // 未保存显示单位时按属性默认值初始化,孔隙度使用空单位.
+ const QString valueDisplayUnit = dataSet.valueDisplayUnit.isEmpty() ?
+ defaultPropertyDisplayUnit(dataSet.property) :
+ dataSet.valueDisplayUnit;
+ populateUnitCombo(m_pNewValueUnitCombo,
+ valueBaseUnit, valueDisplayUnit);
+ populateUnitCombo(m_pValueUnitCombo,
+ valueBaseUnit, valueDisplayUnit);
+ populateUnitCombo(m_pRangeUnitCombo, LENGTH_BASE_UNIT,
+ dataSet.rangeDisplayUnit);
+ dataSet.xDisplayUnit = m_pXUnitCombo->currentText();
+ dataSet.yDisplayUnit = m_pYUnitCombo->currentText();
+ dataSet.valueDisplayUnit = valueBaseUnit.isEmpty() ?
+ QString() : m_pValueUnitCombo->currentText();
+ dataSet.rangeDisplayUnit = m_pRangeUnitCombo->currentText();
+}
+
+void nmWxPropertyInterpolationDlg::updatePointDisplayValues()
+{
+ if(m_nCurrentDataSetIndex < 0 ||
+ m_nCurrentDataSetIndex >= m_vecDataSets.size()) {
+ return;
+ }
+
+ const nmPropertyInterpolationDataSet& dataSet =
+ m_vecDataSets[m_nCurrentDataSetIndex];
+ const QString valueBaseUnit = propertyBaseUnit(dataSet.property);
+ // 测点保留基准值,仅换算表格和地图标签;屏蔽信号避免刷新时反向写回.
+ bool oldTableBlock = m_pPointTable->blockSignals(true);
+ for(int pointIndex = 0; pointIndex < dataSet.points.size(); ++pointIndex) {
+ const int tableRow = pointIndex + FIRST_POINT_ROW;
+ if(tableRow >= m_pPointTable->rowCount()) {
+ break;
+ }
+
+ const nmPropertyInterpolationPointData& point = dataSet.points[pointIndex];
+ QTableWidgetItem* xItem = m_pPointTable->item(tableRow, 0);
+ QTableWidgetItem* yItem = m_pPointTable->item(tableRow, 1);
+ QTableWidgetItem* valueItem = m_pPointTable->item(tableRow, 2);
+ if(xItem != NULL) {
+ xItem->setText(displayValueText(convertedUnitValue(
+ point.x, LENGTH_BASE_UNIT,
+ dataSet.xDisplayUnit)));
+ }
+ if(yItem != NULL) {
+ yItem->setText(displayValueText(convertedUnitValue(
+ point.y, LENGTH_BASE_UNIT,
+ dataSet.yDisplayUnit)));
+ }
+ const double displayValue = convertedUnitValue(
+ point.value, valueBaseUnit,
+ dataSet.valueDisplayUnit);
+ const QString valueText = displayValueText(displayValue);
+ if(valueItem != NULL) {
+ valueItem->setText(valueText);
+ }
+
+ nmObjPoint* marker = markerAt(tableRow);
+ if(marker != NULL) {
+ setMarkerLabel(marker, valueText);
+ marker->update();
+ }
+ }
+ m_pPointTable->blockSignals(oldTableBlock);
+}
+
+void nmWxPropertyInterpolationDlg::clearPointRows()
+{
+ // 只删除测点数据行,第0行的单位下拉框始终保留.
+ if(m_pPointTable != NULL && m_pPointTable->rowCount() > FIRST_POINT_ROW) {
+ m_pPointTable->setRowCount(FIRST_POINT_ROW);
+ }
+ updatePointRowNumbers();
+}
+
+void nmWxPropertyInterpolationDlg::updatePointRowNumbers()
+{
+ if(m_pPointTable == NULL) {
+ return;
+ }
+
+ // 单位行留空,测点数据行始终从1开始连续编号.
+ for(int row = POINT_UNIT_ROW; row < m_pPointTable->rowCount(); ++row) {
+ const QString number = row < FIRST_POINT_ROW ?
+ QString() : QString::number(row - FIRST_POINT_ROW + 1);
+ QTableWidgetItem* headerItem = m_pPointTable->verticalHeaderItem(row);
+ if(headerItem == NULL) {
+ m_pPointTable->setVerticalHeaderItem(row,
+ new QTableWidgetItem(number));
+ }
+ else {
+ headerItem->setText(number);
+ }
+ }
+}
+
+void nmWxPropertyInterpolationDlg::syncDataSetsToManager(bool markModified)
+{
+ if(!m_pDataManager.isNull()) {
+ m_pDataManager->setPropertyInterpolationDataSets(m_vecDataSets);
+ }
+
+ if(markModified && !m_pPlot.isNull()) {
+ m_pPlot->setModified(true);
+ }
+}
+
+void nmWxPropertyInterpolationDlg::updateDataSetButtons()
+{
+ const bool hasCurrent = m_nCurrentDataSetIndex >= 0 &&
+ m_nCurrentDataSetIndex < m_vecDataSets.size();
+ const bool canPickOnMap = hasCurrent && !m_pPlot.isNull() &&
+ m_pPlot->m_pPlotView != NULL && m_pPlot->m_pPlot != NULL;
+ const bool hasValueUnit = hasCurrent &&
+ !propertyBaseUnit(m_vecDataSets[m_nCurrentDataSetIndex].property).isEmpty();
+
+ m_pDataSetCombo->setEnabled(hasCurrent);
+ m_pDeleteDataSetButton->setEnabled(hasCurrent);
+ m_pNameEdit->setEnabled(hasCurrent);
+ m_pPropertyCombo->setEnabled(hasCurrent);
+ m_pNewValueSpin->setEnabled(hasCurrent);
+ m_pNewValueUnitCombo->setEnabled(hasValueUnit);
+ m_pMapPickButton->setEnabled(canPickOnMap);
+ m_pPointTable->setEnabled(hasCurrent);
+ m_pXUnitCombo->setEnabled(hasCurrent);
+ m_pYUnitCombo->setEnabled(hasCurrent);
+ m_pValueUnitCombo->setEnabled(hasValueUnit);
+ m_pShowPointsCheck->setEnabled(hasCurrent);
+ m_pShowLabelsCheck->setEnabled(hasCurrent);
+ m_pNuggetSpin->setEnabled(hasCurrent);
+ m_pSillSpin->setEnabled(hasCurrent);
+ m_pRangeSpin->setEnabled(hasCurrent);
+ m_pRangeUnitCombo->setEnabled(hasCurrent);
+ m_pModelCombo->setEnabled(hasCurrent);
+ updatePointButtons();
+}
+
+void nmWxPropertyInterpolationDlg::updateCalculationDataSetControls()
+{
+ // 批量重建三个下拉框时阻止选择变化信号写回未完成的界面状态.
+ bool wasUpdating = m_bUpdatingUi;
+ m_bUpdatingUi = true;
+ updateCalculationDataSetControl("k", m_pUseKCheck,
+ m_pKCalculationDataSetCombo);
+ updateCalculationDataSetControl("phi", m_pUsePhiCheck,
+ m_pPhiCalculationDataSetCombo);
+ updateCalculationDataSetControl("h", m_pUseHCheck,
+ m_pHCalculationDataSetCombo);
+ m_bUpdatingUi = wasUpdating;
+}
+
+void nmWxPropertyInterpolationDlg::updateCalculationDataSetControl(
+ const QString& property,
+ QCheckBox* checkBox,
+ QComboBox* comboBox)
+{
+ if(checkBox == NULL || comboBox == NULL) {
+ return;
+ }
+
+ // 下拉项保存原数据组下标,并根据useForCalculation恢复当前选择.
+ comboBox->clear();
+ int selectedComboIndex = -1;
+ for(int dataSetIndex = 0; dataSetIndex < m_vecDataSets.size(); ++dataSetIndex) {
+ const nmPropertyInterpolationDataSet& dataSet = m_vecDataSets[dataSetIndex];
+ if(dataSet.property != property) {
+ continue;
+ }
+
+ comboBox->addItem(dataSet.name, dataSetIndex);
+ if(selectedComboIndex < 0 && dataSet.useForCalculation) {
+ selectedComboIndex = comboBox->count() - 1;
+ }
+ }
+
+ comboBox->setCurrentIndex(selectedComboIndex >= 0 ? selectedComboIndex :
+ (comboBox->count() > 0 ? 0 : -1));
+ checkBox->setChecked(selectedComboIndex >= 0);
+ checkBox->setEnabled(comboBox->count() > 0);
+ comboBox->setEnabled(checkBox->isChecked() && comboBox->count() > 0);
+}
+
+void nmWxPropertyInterpolationDlg::saveCalculationSelection(
+ const QString& property,
+ QCheckBox* checkBox,
+ QComboBox* comboBox)
+{
+ // 先清除同属性的旧标记,保证每个属性最多启用一个插值数据组.
+ for(int dataSetIndex = 0; dataSetIndex < m_vecDataSets.size(); ++dataSetIndex) {
+ if(m_vecDataSets[dataSetIndex].property == property) {
+ m_vecDataSets[dataSetIndex].useForCalculation = false;
+ }
+ }
+
+ if(checkBox == NULL || comboBox == NULL || !checkBox->isChecked()) {
+ return;
+ }
+
+ const int selectedDataSetIndex = comboBox->itemData(
+ comboBox->currentIndex()).toInt();
+ if(selectedDataSetIndex >= 0 && selectedDataSetIndex < m_vecDataSets.size() &&
+ m_vecDataSets[selectedDataSetIndex].property == property) {
+ m_vecDataSets[selectedDataSetIndex].useForCalculation = true;
+ }
+}
+
+void nmWxPropertyInterpolationDlg::onDataSetChanged(int index)
+{
+ if(m_bUpdatingUi || index < 0 || index >= m_vecDataSets.size() ||
+ index == m_nCurrentDataSetIndex) {
+ return;
+ }
+
+ saveCurrentDataSet();
+ syncDataSetsToManager(false);
+ m_nCurrentDataSetIndex = index;
+ loadDataSet(index);
+ schedulePreviewRefresh();
+}
+
+void nmWxPropertyInterpolationDlg::onAddDataSet()
+{
+ saveCurrentDataSet();
+ m_vecDataSets.append(createDefaultDataSet());
+ m_vecMarkerNames.append(QStringList());
+
+ int newIndex = m_vecDataSets.size() - 1;
+ bool oldBlock = m_pDataSetCombo->blockSignals(true);
+ m_pDataSetCombo->addItem(m_vecDataSets[newIndex].name);
+ m_pDataSetCombo->setCurrentIndex(newIndex);
+ m_pDataSetCombo->blockSignals(oldBlock);
+
+ m_nCurrentDataSetIndex = newIndex;
+ loadDataSet(newIndex);
+ updateDataSetButtons();
+ updateCalculationDataSetControls();
+ syncDataSetsToManager(true);
+ schedulePreviewRefresh();
+}
+
+void nmWxPropertyInterpolationDlg::onDeleteDataSet()
+{
+ if(m_nCurrentDataSetIndex < 0 ||
+ m_nCurrentDataSetIndex >= m_vecDataSets.size()) {
+ return;
+ }
+
+ int removedIndex = m_nCurrentDataSetIndex;
+ removeDataSetMarkers(removedIndex);
+ m_vecDataSets.remove(removedIndex);
+ m_vecMarkerNames.remove(removedIndex);
+
+ const int newIndex = m_vecDataSets.isEmpty() ? -1 :
+ qMin(removedIndex, m_vecDataSets.size() - 1);
+ bool oldBlock = m_pDataSetCombo->blockSignals(true);
+ m_pDataSetCombo->removeItem(removedIndex);
+ m_pDataSetCombo->setCurrentIndex(newIndex);
+ m_pDataSetCombo->blockSignals(oldBlock);
+
+ m_nCurrentDataSetIndex = newIndex;
+ loadDataSet(newIndex);
+ updateDataSetButtons();
+ updateCalculationDataSetControls();
+ syncDataSetsToManager(true);
+ schedulePreviewRefresh();
+}
+
+void nmWxPropertyInterpolationDlg::onDataSetNameChanged(const QString& name)
+{
+ if(m_bUpdatingUi || m_nCurrentDataSetIndex < 0 ||
+ m_nCurrentDataSetIndex >= m_vecDataSets.size()) {
+ return;
+ }
+
+ m_vecDataSets[m_nCurrentDataSetIndex].name = name;
+ m_pDataSetCombo->setItemText(m_nCurrentDataSetIndex, name);
+ updateCalculationDataSetControls();
+ syncDataSetsToManager(true);
+ schedulePreviewRefresh();
+}
+
+void nmWxPropertyInterpolationDlg::onCurrentDataSetPropertyChanged()
+{
+ if(m_bUpdatingUi || m_nCurrentDataSetIndex < 0 ||
+ m_nCurrentDataSetIndex >= m_vecDataSets.size()) {
+ return;
+ }
+
+ // 数据组切换属性后取消原有求解选择,并切换到对应的基准显示单位.
+ nmPropertyInterpolationDataSet& dataSet =
+ m_vecDataSets[m_nCurrentDataSetIndex];
+ dataSet.useForCalculation = false;
+ dataSet.property = m_pPropertyCombo->itemData(
+ m_pPropertyCombo->currentIndex()).toString();
+ dataSet.valueDisplayUnit = defaultPropertyDisplayUnit(dataSet.property);
+ updateUnitControls(dataSet);
+ m_pNewValueSpin->setValue(0.0);
+ updatePointDisplayValues();
+ saveCurrentDataSet();
+ updateCalculationDataSetControls();
+ syncDataSetsToManager(true);
+ schedulePreviewRefresh();
+}
+
+void nmWxPropertyInterpolationDlg::onCurrentDataSetEdited()
+{
+ if(m_bUpdatingUi) {
+ return;
+ }
+
+ saveCurrentDataSet();
+ syncDataSetsToManager(true);
+ schedulePreviewRefresh();
+}
+
+void nmWxPropertyInterpolationDlg::onXDisplayUnitChanged(const QString& unit)
+{
+ if(m_bUpdatingUi || m_nCurrentDataSetIndex < 0 ||
+ m_nCurrentDataSetIndex >= m_vecDataSets.size()) {
+ return;
+ }
+
+ // 坐标基准值保持为m,仅刷新X列的显示文本.
+ m_vecDataSets[m_nCurrentDataSetIndex].xDisplayUnit = unit;
+ updatePointDisplayValues();
+ syncDataSetsToManager(true);
+}
+
+void nmWxPropertyInterpolationDlg::onYDisplayUnitChanged(const QString& unit)
+{
+ if(m_bUpdatingUi || m_nCurrentDataSetIndex < 0 ||
+ m_nCurrentDataSetIndex >= m_vecDataSets.size()) {
+ return;
+ }
+
+ // 坐标基准值保持为m,仅刷新Y列的显示文本.
+ m_vecDataSets[m_nCurrentDataSetIndex].yDisplayUnit = unit;
+ updatePointDisplayValues();
+ syncDataSetsToManager(true);
+}
+
+void nmWxPropertyInterpolationDlg::onValueDisplayUnitChanged(const QString& unit)
+{
+ if(m_bUpdatingUi || m_nCurrentDataSetIndex < 0 ||
+ m_nCurrentDataSetIndex >= m_vecDataSets.size()) {
+ return;
+ }
+
+ nmPropertyInterpolationDataSet& dataSet =
+ m_vecDataSets[m_nCurrentDataSetIndex];
+ const QString baseUnit = propertyBaseUnit(dataSet.property);
+ if(baseUnit.isEmpty() || unit.isEmpty() ||
+ unit == dataSet.valueDisplayUnit) {
+ return;
+ }
+
+ // 经基准单位中转,切换单位时不会改变待添加值表示的物理量.
+ const double baseNewValue = convertedUnitValue(
+ m_pNewValueSpin->value(),
+ dataSet.valueDisplayUnit, baseUnit);
+ dataSet.valueDisplayUnit = unit;
+
+ // 新值和表头共用显示单位,联动时屏蔽信号以避免递归触发.
+ bool oldBlock = m_pNewValueUnitCombo->blockSignals(true);
+ m_pNewValueUnitCombo->setCurrentIndex(
+ m_pNewValueUnitCombo->findText(unit));
+ m_pNewValueUnitCombo->blockSignals(oldBlock);
+ oldBlock = m_pValueUnitCombo->blockSignals(true);
+ m_pValueUnitCombo->setCurrentIndex(m_pValueUnitCombo->findText(unit));
+ m_pValueUnitCombo->blockSignals(oldBlock);
+ oldBlock = m_pNewValueSpin->blockSignals(true);
+ m_pNewValueSpin->setValue(convertedUnitValue(
+ baseNewValue, baseUnit, unit));
+ m_pNewValueSpin->blockSignals(oldBlock);
+
+ updatePointDisplayValues();
+ syncDataSetsToManager(true);
+ schedulePreviewRefresh();
+}
+
+void nmWxPropertyInterpolationDlg::onRangeDisplayUnitChanged(const QString& unit)
+{
+ if(m_bUpdatingUi || unit.isEmpty() || m_nCurrentDataSetIndex < 0 ||
+ m_nCurrentDataSetIndex >= m_vecDataSets.size()) {
+ return;
+ }
+
+ nmPropertyInterpolationDataSet& dataSet =
+ m_vecDataSets[m_nCurrentDataSetIndex];
+ // 先按旧显示单位还原米制基准值,再使用新单位回显.
+ dataSet.range = convertedUnitValue(
+ m_pRangeSpin->value(), dataSet.rangeDisplayUnit,
+ LENGTH_BASE_UNIT);
+ dataSet.rangeDisplayUnit = unit;
+
+ bool oldBlock = m_pRangeSpin->blockSignals(true);
+ m_pRangeSpin->setValue(convertedUnitValue(
+ dataSet.range, LENGTH_BASE_UNIT, unit));
+ m_pRangeSpin->blockSignals(oldBlock);
+ syncDataSetsToManager(true);
+}
+
+void nmWxPropertyInterpolationDlg::onCalculationSelectionChanged()
+{
+ if(m_bUpdatingUi) {
+ return;
+ }
+
+ // 先保存当前编辑内容,再统一更新三个属性的唯一求解数据组.
+ saveCurrentDataSet();
+ saveCalculationSelection("k", m_pUseKCheck,
+ m_pKCalculationDataSetCombo);
+ saveCalculationSelection("phi", m_pUsePhiCheck,
+ m_pPhiCalculationDataSetCombo);
+ saveCalculationSelection("h", m_pUseHCheck,
+ m_pHCalculationDataSetCombo);
+
+ m_pKCalculationDataSetCombo->setEnabled(m_pUseKCheck->isChecked());
+ m_pPhiCalculationDataSetCombo->setEnabled(m_pUsePhiCheck->isChecked());
+ m_pHCalculationDataSetCombo->setEnabled(m_pUseHCheck->isChecked());
+ syncDataSetsToManager(true);
+}
+
+bool nmWxPropertyInterpolationDlg::eventFilter(QObject* watched, QEvent* event)
+{
+ // 点击表格空白处或其他控件时取消测点行的选中状态.
+ if(event != NULL && event->type() == QEvent::MouseButtonPress && m_pPointTable != NULL) {
+ QWidget* clickedWidget = qobject_cast(watched);
+
+ if(clickedWidget != NULL) {
+ bool isTableViewport = clickedWidget == m_pPointTable->viewport() ||
+ m_pPointTable->viewport()->isAncestorOf(clickedWidget);
+
+ if(clickedWidget == m_pPointTable->viewport()) {
+ QMouseEvent* mouseEvent = static_cast(event);
+
+ if(m_pPointTable->itemAt(mouseEvent->pos()) == NULL) {
+ clearTableSelection();
+ }
+ } else if(!isTableViewport && clickedWidget != m_pDeletePointButton) {
+ clearTableSelection();
+ }
+ }
+ }
+
+ return iDlgBase::eventFilter(watched, event);
+}
+
+void nmWxPropertyInterpolationDlg::onMapPickToggled(bool checked)
+{
+ if(m_pPlot.isNull() || m_pPlot->m_pPlotView == NULL) {
+ return;
+ }
+
+ // 每次切换前先断开旧连接,防止一次地图点击被重复处理.
+ disconnect(m_pPlot->m_pPlotView, SIGNAL(sigLeftClick(QPointF)),
+ this, SLOT(onMapClicked(QPointF)));
+
+ if(checked) {
+ m_pPlot->cancelActiveTools();
+ connect(m_pPlot->m_pPlotView, SIGNAL(sigLeftClick(QPointF)),
+ this, SLOT(onMapClicked(QPointF)));
+ m_pPlot->m_pPlotView->setCursor(Qt::CrossCursor);
+ } else {
+ m_pPlot->m_pPlotView->restoreCursor();
+ }
+}
+
+void nmWxPropertyInterpolationDlg::onMapClicked(const QPointF& position)
+{
+ if(!m_pMapPickButton->isChecked() || m_pPlot.isNull() ||
+ m_pPlot->m_pPlot == NULL || m_nCurrentDataSetIndex < 0) {
+ return;
+ }
+
+ if(!m_pPlot->m_pPlot->getInnerRectF().contains(position)) {
+ return;
+ }
+
+ // 点击位置为绘图区坐标,需要转换成实际数据坐标后保存.
+ QPointF plotPosition = position;
+ QPointF valuePoint = m_pPlot->m_pPlot->getValueForPos(plotPosition);
+ appendPoint(valuePoint);
+}
+
+void nmWxPropertyInterpolationDlg::appendPoint(const QPointF& valuePoint)
+{
+ if(m_nCurrentDataSetIndex < 0 ||
+ m_nCurrentDataSetIndex >= m_vecDataSets.size()) {
+ return;
+ }
+
+ nmPropertyInterpolationDataSet& dataSet = m_vecDataSets[m_nCurrentDataSetIndex];
+ const QString valueBaseUnit = propertyBaseUnit(dataSet.property);
+ const double displayPointValue = m_pNewValueSpin->value();
+ // 属性值按求解器基准单位保存,地图标签继续使用当前显示值.
+ const double pointValue = convertedUnitValue(
+ displayPointValue, dataSet.valueDisplayUnit,
+ valueBaseUnit);
+ nmPropertyInterpolationPointData point(valuePoint.x(), valuePoint.y(), pointValue);
+ QString markerName = createMarker(valuePoint, displayPointValue,
+ dataSet.showPoints, dataSet.showLabels);
+
+ // 测点数据、地图标记和表格行按相同顺序同步追加.
+ dataSet.points.append(point);
+ m_vecMarkerNames[m_nCurrentDataSetIndex].append(markerName);
+
+ bool oldBlock = m_pPointTable->blockSignals(true);
+ appendPointRow(point, markerName);
+ m_pPointTable->blockSignals(oldBlock);
+ m_pPointTable->scrollToBottom();
+ updatePointButtons();
+ syncDataSetsToManager(true);
+ schedulePreviewRefresh();
+}
+
+void nmWxPropertyInterpolationDlg::appendPointRow(
+ const nmPropertyInterpolationPointData& point,
+ const QString& markerName)
+{
+ // rowCount已包含单位行,新插入行天然与points下标保持FIRST_POINT_ROW偏移.
+ int row = m_pPointTable->rowCount();
+ m_pPointTable->insertRow(row);
+ m_pPointTable->setVerticalHeaderItem(
+ row, new QTableWidgetItem(QString::number(
+ row - FIRST_POINT_ROW + 1)));
+
+ QString xUnit = LENGTH_BASE_UNIT;
+ QString yUnit = LENGTH_BASE_UNIT;
+ QString valueUnit;
+ QString valueBaseUnit;
+ if(m_nCurrentDataSetIndex >= 0 &&
+ m_nCurrentDataSetIndex < m_vecDataSets.size()) {
+ const nmPropertyInterpolationDataSet& dataSet =
+ m_vecDataSets[m_nCurrentDataSetIndex];
+ xUnit = dataSet.xDisplayUnit;
+ yUnit = dataSet.yDisplayUnit;
+ valueUnit = dataSet.valueDisplayUnit;
+ valueBaseUnit = propertyBaseUnit(dataSet.property);
+ }
+
+ QTableWidgetItem* xItem = new QTableWidgetItem(displayValueText(
+ convertedUnitValue(point.x, LENGTH_BASE_UNIT, xUnit)));
+ // 将地图标记名称绑定在X列,后续可由表格行直接定位对应标记.
+ xItem->setData(Qt::UserRole, markerName);
+ m_pPointTable->setItem(row, 0, xItem);
+
+ QTableWidgetItem* yItem = new QTableWidgetItem(displayValueText(
+ convertedUnitValue(point.y, LENGTH_BASE_UNIT, yUnit)));
+ m_pPointTable->setItem(row, 1, yItem);
+
+ m_pPointTable->setItem(row, 2, new QTableWidgetItem(displayValueText(
+ convertedUnitValue(point.value, valueBaseUnit, valueUnit))));
+}
+
+QString nmWxPropertyInterpolationDlg::createMarker(const QPointF& valuePosition,
+ double value,
+ bool showPoints,
+ bool showLabels)
+{
+ if(m_pPlot.isNull() || m_pPlot->m_pPlot == NULL) {
+ return QString();
+ }
+
+ QString markerName;
+ do {
+ markerName = QString("__PropertyInterpolationPoint_%1").arg(++m_nNextPointId);
+ } while(m_pPlot->m_pPlot->getObjByName(markerName) != NULL);
+
+ // 地图标记仅用于临时显示,不应单独改变工程修改状态.
+ bool wasModified = m_pPlot->isModified();
+ PropertyInterpolationMarker* marker = new PropertyInterpolationMarker(
+ markerName,
+ m_pPlot->m_pPlot->getMainAxisX(),
+ m_pPlot->m_pPlot->getMainAxisY());
+ m_pPlot->bindObjSignals(marker);
+
+ if(!m_pPlot->m_pPlot->addOneObj(marker)) {
+ delete marker;
+ m_pPlot->setModified(wasModified);
+ return QString();
+ }
+
+ QVector values;
+ values.append(valuePosition);
+ marker->setAllValues(values);
+ m_pPlot->slotObjCompleted(marker);
+ setMarkerLabel(marker, QString::number(value, 'g', 10));
+ marker->setReadOnly(true);
+ marker->setLockPos(true);
+ marker->showSubObjs(showPoints && showLabels);
+ marker->setVisible(showPoints);
+ marker->deselect(true);
+ marker->update();
+ m_pPlot->setModified(wasModified);
+ return markerName;
+}
+
+void nmWxPropertyInterpolationDlg::createMarkersForAllDataSets()
+{
+ if(m_pPlot.isNull() || m_pPlot->m_pPlot == NULL) {
+ return;
+ }
+
+ // 地图标签使用显示单位,数据组中的测点基准值保持不变.
+ for(int dataSetIndex = 0; dataSetIndex < m_vecDataSets.size(); ++dataSetIndex) {
+ const nmPropertyInterpolationDataSet& dataSet = m_vecDataSets[dataSetIndex];
+ QStringList markerNames;
+
+ for(int pointIndex = 0; pointIndex < dataSet.points.size(); ++pointIndex) {
+ const nmPropertyInterpolationPointData& point = dataSet.points[pointIndex];
+ QPointF valuePosition(point.x, point.y);
+ const double displayValue = convertedUnitValue(
+ point.value, propertyBaseUnit(dataSet.property),
+ dataSet.valueDisplayUnit);
+ markerNames.append(createMarker(valuePosition, displayValue,
+ dataSet.showPoints, dataSet.showLabels));
+ }
+
+ m_vecMarkerNames[dataSetIndex] = markerNames;
+ }
+}
+
+void nmWxPropertyInterpolationDlg::removeDataSetMarkers(int dataSetIndex)
+{
+ if(dataSetIndex < 0 || dataSetIndex >= m_vecMarkerNames.size()) {
+ return;
+ }
+
+ const QStringList markerNames = m_vecMarkerNames[dataSetIndex];
+ for(int i = 0; i < markerNames.size(); ++i) {
+ removeMarkerByName(markerNames[i]);
+ }
+ m_vecMarkerNames[dataSetIndex].clear();
+}
+
+void nmWxPropertyInterpolationDlg::removeAllMarkers()
+{
+ for(int i = 0; i < m_vecMarkerNames.size(); ++i) {
+ removeDataSetMarkers(i);
+ }
+ m_vecMarkerNames.clear();
+}
+
+QString nmWxPropertyInterpolationDlg::markerNameAt(int row) const
+{
+ if(m_pPointTable == NULL || row < FIRST_POINT_ROW ||
+ row >= m_pPointTable->rowCount()) {
+ return QString();
+ }
+
+ QTableWidgetItem* item = m_pPointTable->item(row, 0);
+ return item == NULL ? QString() : item->data(Qt::UserRole).toString();
+}
+
+nmObjPoint* nmWxPropertyInterpolationDlg::markerByName(const QString& markerName) const
+{
+ if(m_pPlot.isNull() || m_pPlot->m_pPlot == NULL || markerName.isEmpty()) {
+ return NULL;
+ }
+
+ return dynamic_cast(m_pPlot->m_pPlot->getObjByName(markerName));
+}
+
+nmObjPoint* nmWxPropertyInterpolationDlg::markerAt(int row) const
+{
+ return markerByName(markerNameAt(row));
+}
+
+void nmWxPropertyInterpolationDlg::removeMarkerByName(const QString& markerName)
+{
+ if(m_pPlot.isNull() || m_pPlot->m_pPlot == NULL || markerName.isEmpty() ||
+ m_pPlot->m_pPlot->getObjByName(markerName) == NULL) {
+ return;
+ }
+
+ bool wasModified = m_pPlot->isModified();
+ m_pPlot->m_pPlot->removeObjByName(markerName);
+ m_pPlot->setModified(wasModified);
+}
+
+void nmWxPropertyInterpolationDlg::onPointSelectionChanged()
+{
+ // 单位行只用于切换显示单位,不作为可删除的测点行.
+ if(m_pPointTable->currentRow() == POINT_UNIT_ROW) {
+ clearTableSelection();
+ return;
+ }
+ updatePointButtons();
+}
+
+void nmWxPropertyInterpolationDlg::onPointItemChanged(QTableWidgetItem* item)
+{
+ // 表格行减去单位行偏移后,才是数据组中的测点下标.
+ const int pointIndex = item == NULL ? -1 :
+ item->row() - FIRST_POINT_ROW;
+ if(m_bUpdatingUi || item == NULL || item->column() < 0 ||
+ item->column() > 2 ||
+ pointIndex < 0 ||
+ m_nCurrentDataSetIndex < 0 ||
+ m_nCurrentDataSetIndex >= m_vecDataSets.size() ||
+ pointIndex >= m_vecDataSets[m_nCurrentDataSetIndex].points.size()) {
+ return;
+ }
+
+ nmPropertyInterpolationDataSet& dataSet =
+ m_vecDataSets[m_nCurrentDataSetIndex];
+ nmPropertyInterpolationPointData& point = dataSet.points[pointIndex];
+
+ // X、Y及属性值分别按当前显示单位换算回数据中心使用的基准单位.
+ QString baseUnit;
+ QString displayUnit;
+ double oldBaseValue = 0.0;
+ if(item->column() == 0) {
+ baseUnit = LENGTH_BASE_UNIT;
+ displayUnit = dataSet.xDisplayUnit;
+ oldBaseValue = point.x;
+ }
+ else if(item->column() == 1) {
+ baseUnit = LENGTH_BASE_UNIT;
+ displayUnit = dataSet.yDisplayUnit;
+ oldBaseValue = point.y;
+ }
+ else {
+ baseUnit = propertyBaseUnit(dataSet.property);
+ displayUnit = dataSet.valueDisplayUnit;
+ oldBaseValue = point.value;
+ }
+
+ bool valueOk = false;
+ const double displayValue = item->text().toDouble(&valueOk);
+ if(!valueOk || (item->column() == 2 && displayValue < 0.0)) {
+ // 坐标允许为负数;属性值仍要求非负,非法输入恢复为修改前的值.
+ const double oldDisplayValue = convertedUnitValue(
+ oldBaseValue, baseUnit, displayUnit);
+ const bool oldBlock = m_pPointTable->blockSignals(true);
+ item->setText(displayValueText(oldDisplayValue));
+ m_pPointTable->blockSignals(oldBlock);
+ return;
+ }
+
+ const double baseValue = convertedUnitValue(
+ displayValue, displayUnit, baseUnit);
+ if(item->column() == 0) {
+ point.x = baseValue;
+ }
+ else if(item->column() == 1) {
+ point.y = baseValue;
+ }
+ else {
+ point.value = baseValue;
+ }
+
+ const QString displayText = displayValueText(displayValue);
+ if(item->text() != displayText) {
+ const bool oldBlock = m_pPointTable->blockSignals(true);
+ item->setText(displayText);
+ m_pPointTable->blockSignals(oldBlock);
+ }
+
+ // 坐标修改后移动Map标记,属性值修改后刷新标记标签.
+ nmObjPoint* marker = markerAt(item->row());
+ if(marker != NULL) {
+ if(item->column() < 2) {
+ QVector positions;
+ positions.append(QPointF(point.x, point.y));
+ marker->setAllValues(positions);
+ }
+ else {
+ setMarkerLabel(marker, displayText);
+ }
+ marker->update();
+ }
+ syncDataSetsToManager(true);
+ schedulePreviewRefresh();
+}
+
+void nmWxPropertyInterpolationDlg::onDeleteSelectedPoint()
+{
+ int row = m_pPointTable->currentRow();
+ // 同时删除相同下标的数据、地图标记和表格行,保持三者一一对应.
+ const int pointIndex = row - FIRST_POINT_ROW;
+ if(pointIndex < 0 || m_nCurrentDataSetIndex < 0 ||
+ m_nCurrentDataSetIndex >= m_vecDataSets.size()) {
+ return;
+ }
+
+ removeMarkerByName(markerNameAt(row));
+ if(pointIndex < m_vecDataSets[m_nCurrentDataSetIndex].points.size()) {
+ m_vecDataSets[m_nCurrentDataSetIndex].points.remove(pointIndex);
+ }
+ if(pointIndex < m_vecMarkerNames[m_nCurrentDataSetIndex].size()) {
+ m_vecMarkerNames[m_nCurrentDataSetIndex].removeAt(pointIndex);
+ }
+ m_pPointTable->removeRow(row);
+ updatePointRowNumbers();
+ clearTableSelection();
+ updatePointButtons();
+ syncDataSetsToManager(true);
+ schedulePreviewRefresh();
+}
+
+void nmWxPropertyInterpolationDlg::onClearPoints()
+{
+ if(m_nCurrentDataSetIndex < 0 ||
+ m_nCurrentDataSetIndex >= m_vecDataSets.size()) {
+ return;
+ }
+
+ removeDataSetMarkers(m_nCurrentDataSetIndex);
+ m_vecDataSets[m_nCurrentDataSetIndex].points.clear();
+ clearPointRows();
+ clearTableSelection();
+ updatePointButtons();
+ syncDataSetsToManager(true);
+ schedulePreviewRefresh();
+}
+
+void nmWxPropertyInterpolationDlg::onShowPointsToggled(bool checked)
+{
+ if(m_bUpdatingUi || m_nCurrentDataSetIndex < 0 ||
+ m_nCurrentDataSetIndex >= m_vecDataSets.size()) {
+ return;
+ }
+
+ m_vecDataSets[m_nCurrentDataSetIndex].showPoints = checked;
+ updateCurrentMarkerVisibility();
+ syncDataSetsToManager(true);
+ schedulePreviewRefresh();
+}
+
+void nmWxPropertyInterpolationDlg::onShowLabelsToggled(bool checked)
+{
+ if(m_bUpdatingUi || m_nCurrentDataSetIndex < 0 ||
+ m_nCurrentDataSetIndex >= m_vecDataSets.size()) {
+ return;
+ }
+
+ m_vecDataSets[m_nCurrentDataSetIndex].showLabels = checked;
+ updateCurrentMarkerVisibility();
+ syncDataSetsToManager(true);
+ schedulePreviewRefresh();
+}
+
+void nmWxPropertyInterpolationDlg::clearTableSelection()
+{
+ m_pPointTable->clearSelection();
+ m_pPointTable->setCurrentCell(-1, -1);
+}
+
+void nmWxPropertyInterpolationDlg::updatePointButtons()
+{
+ const bool hasCurrent = m_nCurrentDataSetIndex >= 0 &&
+ m_nCurrentDataSetIndex < m_vecDataSets.size();
+ const bool hasPoints = hasCurrent &&
+ !m_vecDataSets[m_nCurrentDataSetIndex].points.isEmpty();
+
+ // 已有测点的数值含义已经确定,需清空测点后才能切换数据组属性.
+ m_pPropertyCombo->setEnabled(hasCurrent && !hasPoints);
+ m_pPropertyCombo->setToolTip(hasPoints ?
+ interpolationText("Clear measurement points before changing the property.") :
+ QString());
+ m_pDeletePointButton->setEnabled(
+ hasCurrent && m_pPointTable->currentRow() >= FIRST_POINT_ROW);
+ m_pClearPointsButton->setEnabled(
+ hasCurrent && m_pPointTable->rowCount() > FIRST_POINT_ROW);
+ // Kriging预览至少需要两个已知测点.
+ m_pPreviewButton->setEnabled(hasCurrent &&
+ m_vecDataSets[m_nCurrentDataSetIndex].points.size() >= 2);
+}
+
+void nmWxPropertyInterpolationDlg::onPreview()
+{
+ if(m_pPreviewRefreshTimer != NULL) {
+ m_pPreviewRefreshTimer->stop();
+ }
+ updatePreviewWindow(true);
+}
+
+void nmWxPropertyInterpolationDlg::schedulePreviewRefresh()
+{
+ if(m_pPreviewDialog.isNull() || !m_pPreviewDialog->isVisible() ||
+ m_pPreviewRefreshTimer == NULL) {
+ return;
+ }
+
+ // 连续编辑参数时重置计时,仅对最终状态执行一次插值计算.
+ m_pPreviewRefreshTimer->start();
+}
+
+void nmWxPropertyInterpolationDlg::refreshPreview()
+{
+ if(m_pPreviewDialog.isNull() || !m_pPreviewDialog->isVisible()) {
+ return;
+ }
+
+ updatePreviewWindow(false);
+}
+
+void nmWxPropertyInterpolationDlg::showPreviewError(
+ const QString& message,
+ bool activateWindow)
+{
+ const QString errorText = message.isEmpty() ?
+ interpolationText("Preview Failed") : message;
+ QString dataSetName;
+ if(m_nCurrentDataSetIndex >= 0 &&
+ m_nCurrentDataSetIndex < m_vecDataSets.size()) {
+ dataSetName = m_vecDataSets[m_nCurrentDataSetIndex].name;
+ }
+
+ if(!m_pPreviewDialog.isNull()) {
+ m_pPreviewDialog->showMessage(dataSetName, errorText);
+ if(activateWindow) {
+ m_pPreviewDialog->show();
+ m_pPreviewDialog->raise();
+ m_pPreviewDialog->activateWindow();
+ }
+ }
+ else if(activateWindow) {
+ QMessageBox::warning(this, interpolationText("Preview Failed"), errorText);
+ }
+}
+
+void nmWxPropertyInterpolationDlg::updatePreviewWindow(bool activateWindow)
+{
+ if(m_nCurrentDataSetIndex < 0 ||
+ m_nCurrentDataSetIndex >= m_vecDataSets.size() ||
+ m_pDataManager.isNull()) {
+ showPreviewError(interpolationText("Preview Failed"), activateWindow);
+ return;
+ }
+
+ saveCurrentDataSet();
+ const nmPropertyInterpolationDataSet& dataSet =
+ m_vecDataSets[m_nCurrentDataSetIndex];
+
+ // 预览范围直接使用储层边界,与地图中的数据坐标保持一致.
+ QVector outlinePoints;
+ QRectF previewBounds;
+ if(!createPreviewOutline(m_pDataManager->getOutlineData(),
+ outlinePoints, previewBounds)) {
+ showPreviewError(
+ interpolationText("Please create a valid reservoir boundary before previewing."),
+ activateWindow);
+ return;
+ }
+
+ QVector measurementPoints;
+ QVector measurementValues;
+ measurementPoints.reserve(dataSet.points.size());
+ measurementValues.reserve(dataSet.points.size());
+ for(int i = 0; i < dataSet.points.size(); ++i) {
+ measurementPoints.append(QPointF(dataSet.points[i].x,
+ dataSet.points[i].y));
+ measurementValues.append(dataSet.points[i].value);
+ }
+
+ // 按行生成规则待插值点,输出下标与预览网格下标保持一致;
+ // 较疏采样可使分级色带边界更清晰.
+ const int columnCount = 19;
+ const int rowCount = 19;
+ QVector targetPoints;
+ targetPoints.reserve(columnCount * rowCount);
+ for(int row = 0; row < rowCount; ++row) {
+ const double y = previewBounds.top() +
+ previewBounds.height() * row / (rowCount - 1);
+ for(int column = 0; column < columnCount; ++column) {
+ const double x = previewBounds.left() +
+ previewBounds.width() * column / (columnCount - 1);
+ targetPoints.append(QPointF(x, y));
+ }
+ }
+
+ QVector interpolationValues;
+ QString errorMessage;
+ QApplication::setOverrideCursor(Qt::WaitCursor);
+ // 通过统一封装调用Kriging接口,返回值顺序与待插值点一致.
+ const bool calculationSucceeded = nmCalculationUtils::calculateKriging(
+ targetPoints,
+ measurementPoints,
+ measurementValues,
+ dataSet.nugget,
+ dataSet.sill,
+ dataSet.range,
+ dataSet.model,
+ m_pDataManager->getLicensePath(),
+ interpolationValues,
+ &errorMessage);
+ QApplication::restoreOverrideCursor();
+
+ if(!calculationSucceeded) {
+ showPreviewError(errorMessage, activateWindow);
+ return;
+ }
+
+ // Kriging使用内部基准值;渲染前统一转换表面和测点的显示单位.
+ const QString valueBaseUnit = propertyBaseUnit(dataSet.property);
+ QVector displayInterpolationValues;
+ displayInterpolationValues.reserve(interpolationValues.size());
+ for(int i = 0; i < interpolationValues.size(); ++i) {
+ displayInterpolationValues.append(convertedUnitValue(
+ interpolationValues[i],
+ valueBaseUnit,
+ dataSet.valueDisplayUnit));
+ }
+ QVector displayMeasurementValues;
+ displayMeasurementValues.reserve(measurementValues.size());
+ for(int i = 0; i < measurementValues.size(); ++i) {
+ displayMeasurementValues.append(convertedUnitValue(
+ measurementValues[i],
+ valueBaseUnit,
+ dataSet.valueDisplayUnit));
+ }
+ QString scalarTitle = m_pPropertyCombo->currentText();
+ if(!dataSet.valueDisplayUnit.isEmpty()) {
+ scalarTitle += QString(" (%1)").arg(dataSet.valueDisplayUnit);
+ }
+
+ // 直接读取Map中实际显示的井,避免“参与计算井”尚未设置时预览中没有井位.
+ QVector wellPoints;
+ QStringList wellNames;
+ const QVector wellPlots = m_pPlot.isNull() ?
+ QVector() : m_pPlot->getWellPlots();
+ for(int i = 0; i < wellPlots.size(); ++i) {
+ nmObjPointWell* wellPlot = wellPlots[i];
+ if(wellPlot == NULL || wellPlot->getWellData() == NULL) {
+ continue;
+ }
+
+ const QVector wellInformation = wellPlot->getWellInformation();
+ const QString wellName = wellPlot->getWellData()->getName();
+ if(wellInformation.size() < 2 || wellName.isEmpty() ||
+ wellNames.contains(wellName)) {
+ continue;
+ }
+
+ const QPointF wellPoint(wellInformation[0], wellInformation[1]);
+ if(previewBounds.contains(wellPoint)) {
+ wellPoints.append(wellPoint);
+ wellNames.append(wellName);
+ }
+ }
+
+ // 预览窗口只负责裁剪和渲染,不修改数据组及正式求解参数.
+ if(m_pPreviewDialog.isNull()) {
+ m_pPreviewDialog = new nmWxPropertyInterpolationPreviewDlg(
+ dataSet.name,
+ scalarTitle,
+ previewBounds,
+ columnCount,
+ rowCount,
+ displayInterpolationValues,
+ measurementPoints,
+ displayMeasurementValues,
+ outlinePoints,
+ wellPoints,
+ wellNames,
+ dataSet.showPoints,
+ dataSet.showLabels,
+ this);
+ m_pPreviewDialog->setAttribute(Qt::WA_DeleteOnClose, true);
+ }
+ else {
+ m_pPreviewDialog->updatePreview(
+ dataSet.name,
+ scalarTitle,
+ previewBounds,
+ columnCount,
+ rowCount,
+ displayInterpolationValues,
+ measurementPoints,
+ displayMeasurementValues,
+ outlinePoints,
+ wellPoints,
+ wellNames,
+ dataSet.showPoints,
+ dataSet.showLabels);
+ }
+
+ if(activateWindow) {
+ m_pPreviewDialog->show();
+ m_pPreviewDialog->raise();
+ m_pPreviewDialog->activateWindow();
+ }
+}
+
+void nmWxPropertyInterpolationDlg::updateCurrentMarkerVisibility()
+{
+ // 地图上只显示当前数据组的测点,其他数据组统一隐藏.
+ for(int dataSetIndex = 0;
+ dataSetIndex < m_vecMarkerNames.size(); ++dataSetIndex) {
+ const bool isCurrentDataSet = dataSetIndex == m_nCurrentDataSetIndex &&
+ dataSetIndex < m_vecDataSets.size();
+ const bool showPoints = isCurrentDataSet &&
+ m_vecDataSets[dataSetIndex].showPoints;
+ const bool showLabels = showPoints &&
+ m_vecDataSets[dataSetIndex].showLabels;
+ const QStringList markerNames = m_vecMarkerNames[dataSetIndex];
+
+ for(int markerIndex = 0; markerIndex < markerNames.size(); ++markerIndex) {
+ nmObjPoint* marker = markerByName(markerNames[markerIndex]);
+ if(marker != NULL) {
+ marker->setVisible(showPoints);
+ marker->showSubObjs(showLabels);
+ marker->update();
+ }
+ }
+ }
+
+ if(!m_pPlot.isNull() && m_pPlot->m_pPlotView != NULL) {
+ m_pPlot->m_pPlotView->updateViewport();
+ }
+}
diff --git a/Src/nmNum/nmSubWxs/nmWxPropertyInterpolationPreviewDlg.cpp b/Src/nmNum/nmSubWxs/nmWxPropertyInterpolationPreviewDlg.cpp
new file mode 100644
index 0000000..67b0dd7
--- /dev/null
+++ b/Src/nmNum/nmSubWxs/nmWxPropertyInterpolationPreviewDlg.cpp
@@ -0,0 +1,620 @@
+#include "nmWxPropertyInterpolationPreviewDlg.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace
+{
+QString previewText(const char* sourceText)
+{
+ return QCoreApplication::translate("nmWxPropertyInterpolationPreviewDlg", sourceText);
+}
+
+vtkSmartPointer createPreviewLookupTable(double minimum,
+ double maximum)
+{
+ vtkSmartPointer lookupTable =
+ vtkSmartPointer::New();
+ lookupTable->SetNumberOfTableValues(256);
+ lookupTable->SetRange(minimum, maximum);
+ lookupTable->SetHueRange(0.60, 0.02);
+ lookupTable->SetSaturationRange(0.50, 0.50);
+ lookupTable->SetValueRange(0.96, 0.96);
+ lookupTable->Build();
+ return lookupTable;
+}
+
+void showPreviewFailure(vtkRenderer* renderer,
+ vtkRenderWindow* renderWindow,
+ const QString& message)
+{
+ if(renderer == NULL || renderWindow == NULL) {
+ return;
+ }
+
+ vtkSmartPointer messageActor =
+ vtkSmartPointer::New();
+ const QString displayMessage = message.isEmpty() ?
+ previewText("Preview Failed") : message;
+ messageActor->SetInput(displayMessage.toUtf8().constData());
+ messageActor->SetDisplayPosition(24, 24);
+ messageActor->GetTextProperty()->SetColor(0.75, 0.15, 0.12);
+ messageActor->GetTextProperty()->SetFontSize(16);
+ renderer->AddActor2D(messageActor);
+ renderWindow->Render();
+}
+}
+
+nmWxPropertyInterpolationPreviewDlg::nmWxPropertyInterpolationPreviewDlg(
+ const QString& dataSetName,
+ const QString& scalarTitle,
+ const QRectF& bounds,
+ int columnCount,
+ int rowCount,
+ const QVector& interpolationValues,
+ const QVector& measurementPoints,
+ const QVector& measurementValues,
+ const QVector& outlinePoints,
+ const QVector& wellPoints,
+ const QStringList& wellNames,
+ bool showMeasurementPoints,
+ bool showMeasurementLabels,
+ QWidget* parent)
+ : iDlgBase(parent),
+ m_pVtkWidget(NULL)
+{
+ setWindowModality(Qt::NonModal);
+ setModal(false);
+
+ QVBoxLayout* mainLayout = new QVBoxLayout(this);
+ mainLayout->setContentsMargins(8, 8, 8, 8);
+ mainLayout->setSpacing(8);
+
+ m_pVtkWidget = new QVTKWidget(this);
+ m_pVtkWidget->setSizePolicy(QSizePolicy::Expanding,
+ QSizePolicy::Expanding);
+ mainLayout->addWidget(m_pVtkWidget, 1);
+
+ QHBoxLayout* buttonLayout = new QHBoxLayout;
+ buttonLayout->addStretch();
+ QPushButton* closeButton = new QPushButton(previewText("Close"), this);
+ buttonLayout->addWidget(closeButton);
+ mainLayout->addLayout(buttonLayout);
+ connect(closeButton, SIGNAL(clicked()), this, SLOT(close()));
+
+ updatePreview(dataSetName, scalarTitle, bounds, columnCount, rowCount,
+ interpolationValues, measurementPoints,
+ measurementValues, outlinePoints, wellPoints, wellNames,
+ showMeasurementPoints, showMeasurementLabels);
+}
+
+QSize nmWxPropertyInterpolationPreviewDlg::sizeHint() const
+{
+ QDesktopWidget* desktop = QApplication::desktop();
+ if(desktop == NULL) {
+ return iDlgBase::sizeHint();
+ }
+
+ // 预览窗口随当前屏幕可用区域调整,避免固定像素尺寸在不同分辨率下失衡.
+ const QRect availableRect = desktop->availableGeometry(this);
+ return QSize(availableRect.width() * 1 / 2,
+ availableRect.height() * 4 / 5);
+}
+
+void nmWxPropertyInterpolationPreviewDlg::updatePreview(
+ const QString& dataSetName,
+ const QString& scalarTitle,
+ const QRectF& bounds,
+ int columnCount,
+ int rowCount,
+ const QVector& interpolationValues,
+ const QVector& measurementPoints,
+ const QVector& measurementValues,
+ const QVector& outlinePoints,
+ const QVector& wellPoints,
+ const QStringList& wellNames,
+ bool showMeasurementPoints,
+ bool showMeasurementLabels)
+{
+ setWindowTitle(previewText("Interpolation Preview") + " - " + dataSetName);
+ initializeRenderer(scalarTitle, bounds, columnCount, rowCount,
+ interpolationValues, measurementPoints,
+ measurementValues, outlinePoints, wellPoints, wellNames,
+ showMeasurementPoints, showMeasurementLabels);
+}
+
+void nmWxPropertyInterpolationPreviewDlg::showMessage(
+ const QString& dataSetName,
+ const QString& message)
+{
+ if(m_pVtkWidget == NULL) {
+ return;
+ }
+
+ QString windowTitle = previewText("Interpolation Preview");
+ if(!dataSetName.isEmpty()) {
+ windowTitle += " - " + dataSetName;
+ }
+ setWindowTitle(windowTitle);
+
+ vtkSmartPointer renderer = vtkSmartPointer::New();
+ renderer->SetBackground(1.0, 1.0, 1.0);
+
+ vtkSmartPointer renderWindow =
+ vtkSmartPointer::New();
+ renderWindow->SetMultiSamples(0);
+ renderWindow->AddRenderer(renderer);
+ m_pVtkWidget->SetRenderWindow(renderWindow);
+ showPreviewFailure(renderer, renderWindow, message);
+}
+
+void nmWxPropertyInterpolationPreviewDlg::initializeRenderer(
+ const QString& scalarTitle,
+ const QRectF& bounds,
+ int columnCount,
+ int rowCount,
+ const QVector& interpolationValues,
+ const QVector& measurementPoints,
+ const QVector& measurementValues,
+ const QVector& outlinePoints,
+ const QVector& wellPoints,
+ const QStringList& wellNames,
+ bool showMeasurementPoints,
+ bool showMeasurementLabels)
+{
+ if(m_pVtkWidget == NULL) {
+ return;
+ }
+
+ // 显式创建渲染窗口,避免使用尚未初始化的QVTKWidget默认窗口.
+ vtkSmartPointer renderer = vtkSmartPointer::New();
+ renderer->SetBackground(1.0, 1.0, 1.0);
+
+ vtkSmartPointer renderWindow =
+ vtkSmartPointer::New();
+ renderWindow->SetMultiSamples(0);
+ renderWindow->AddRenderer(renderer);
+ m_pVtkWidget->SetRenderWindow(renderWindow);
+
+ if(columnCount < 2 || rowCount < 2 ||
+ bounds.width() <= 0.0 || bounds.height() <= 0.0 ||
+ interpolationValues.size() != columnCount * rowCount) {
+ showPreviewFailure(renderer, renderWindow, previewText("Preview Failed"));
+ return;
+ }
+
+ // 规则采样点使用Kriging结果,测点作为额外顶点直接使用已知值.
+ vtkSmartPointer surfacePoints =
+ vtkSmartPointer::New();
+ vtkSmartPointer scalarArray =
+ vtkSmartPointer::New();
+ scalarArray->SetName("InterpolatedValue");
+ scalarArray->SetNumberOfComponents(1);
+
+ const double spacingX = bounds.width() / (columnCount - 1);
+ const double spacingY = bounds.height() / (rowCount - 1);
+ for(int row = 0; row < rowCount; ++row) {
+ const double y = bounds.top() + spacingY * row;
+ for(int column = 0; column < columnCount; ++column) {
+ const int valueIndex = row * columnCount + column;
+ const double x = bounds.left() + spacingX * column;
+ surfacePoints->InsertNextPoint(x, y, 0.0);
+ scalarArray->InsertNextValue(interpolationValues[valueIndex]);
+ }
+ }
+
+ if(measurementPoints.size() == measurementValues.size()) {
+ const double coordinateTolerance = qMax(
+ qMax(bounds.width(), bounds.height()) * 1.0e-10,
+ 1.0e-12);
+ const int regularPointCount = surfacePoints->GetNumberOfPoints();
+ for(int i = 0; i < measurementPoints.size(); ++i) {
+ vtkIdType matchingPointId = -1;
+ for(int pointIndex = 0; pointIndex < regularPointCount; ++pointIndex) {
+ double regularPoint[3] = { 0.0, 0.0, 0.0 };
+ surfacePoints->GetPoint(pointIndex, regularPoint);
+ if(qAbs(regularPoint[0] - measurementPoints[i].x()) <= coordinateTolerance &&
+ qAbs(regularPoint[1] - measurementPoints[i].y()) <= coordinateTolerance) {
+ matchingPointId = pointIndex;
+ break;
+ }
+ }
+
+ if(matchingPointId >= 0) {
+ scalarArray->SetValue(matchingPointId, measurementValues[i]);
+ }
+ else {
+ surfacePoints->InsertNextPoint(measurementPoints[i].x(),
+ measurementPoints[i].y(), 0.0);
+ scalarArray->InsertNextValue(measurementValues[i]);
+ }
+ }
+ }
+
+ vtkSmartPointer surfaceData =
+ vtkSmartPointer::New();
+ surfaceData->SetPoints(surfacePoints);
+ surfaceData->GetPointData()->SetScalars(scalarArray);
+
+ vtkSmartPointer triangulationFilter =
+ vtkSmartPointer::New();
+ triangulationFilter->SetInputData(surfaceData);
+ triangulationFilter->SetProjectionPlaneMode(VTK_DELAUNAY_XY_PLANE);
+ triangulationFilter->SetTolerance(0.0);
+ triangulationFilter->BoundingTriangulationOff();
+ triangulationFilter->Update();
+
+ // 默认使用完整三角网格;仅在裁剪结果有效且保留标量时切换.
+ vtkPolyData* visibleSurface = triangulationFilter->GetOutput();
+ vtkSmartPointer extractFilter;
+ vtkSmartPointer selectionLoop;
+ vtkSmartPointer selectionPoints;
+ if(outlinePoints.size() >= 3) {
+ selectionPoints = vtkSmartPointer::New();
+ for(int i = 0; i < outlinePoints.size(); ++i) {
+ selectionPoints->InsertNextPoint(outlinePoints[i].x(),
+ outlinePoints[i].y(), 0.0);
+ }
+
+ selectionLoop = vtkSmartPointer::New();
+ selectionLoop->SetLoop(selectionPoints);
+ selectionLoop->AutomaticNormalGenerationOff();
+ selectionLoop->SetNormal(0.0, 0.0, 1.0);
+
+ extractFilter = vtkSmartPointer::New();
+ extractFilter->SetInputConnection(triangulationFilter->GetOutputPort());
+ extractFilter->SetImplicitFunction(selectionLoop);
+ extractFilter->ExtractInsideOn();
+ extractFilter->ExtractBoundaryCellsOn();
+ extractFilter->Update();
+ vtkPolyData* extractedSurface = extractFilter->GetOutput();
+ if(extractedSurface != NULL &&
+ extractedSurface->GetNumberOfPoints() > 0 &&
+ extractedSurface->GetPointData() != NULL &&
+ extractedSurface->GetPointData()->GetScalars() != NULL) {
+ visibleSurface = extractedSurface;
+ }
+ }
+
+ if(visibleSurface == NULL || visibleSurface->GetNumberOfPoints() == 0 ||
+ visibleSurface->GetPointData() == NULL ||
+ visibleSurface->GetPointData()->GetScalars() == NULL) {
+ showPreviewFailure(renderer, renderWindow, previewText("Preview Failed"));
+ return;
+ }
+
+ vtkDataArray* interpolatedScalars =
+ visibleSurface->GetPointData()->GetScalars();
+ visibleSurface->GetPointData()->SetScalars(interpolatedScalars);
+
+ // 颜色条使用测点值范围,避免规则采样未命中测点时最大、最小值向内收缩.
+ double displayMinimum = 0.0;
+ double displayMaximum = 0.0;
+ if(!measurementValues.isEmpty()) {
+ displayMinimum = measurementValues[0];
+ displayMaximum = measurementValues[0];
+ for(int i = 1; i < measurementValues.size(); ++i) {
+ displayMinimum = qMin(displayMinimum, measurementValues[i]);
+ displayMaximum = qMax(displayMaximum, measurementValues[i]);
+ }
+ }
+ else {
+ double displayRange[2] = { 0.0, 0.0 };
+ visibleSurface->GetPointData()->GetScalars()->GetRange(displayRange);
+ displayMinimum = displayRange[0];
+ displayMaximum = displayRange[1];
+ }
+ if(qAbs(displayMaximum - displayMinimum) < 1.0e-12) {
+ const double padding = qMax(qAbs(displayMinimum) * 0.01, 1.0e-6);
+ displayMinimum -= padding;
+ displayMaximum += padding;
+ }
+
+ vtkSmartPointer lookupTable =
+ createPreviewLookupTable(displayMinimum, displayMaximum);
+
+ // 将连续点标量划分为8级色带,Mapper按CellData进行分级着色.
+ const int colorBandCount = 8;
+ vtkSmartPointer bandFilter =
+ vtkSmartPointer::New();
+ bandFilter->SetInputData(visibleSurface);
+ bandFilter->GenerateValues(colorBandCount + 1,
+ displayMinimum, displayMaximum);
+ bandFilter->SetScalarModeToValue();
+ bandFilter->GenerateContourEdgesOff();
+
+ vtkSmartPointer surfaceMapper =
+ vtkSmartPointer::New();
+ surfaceMapper->SetInputConnection(bandFilter->GetOutputPort());
+ surfaceMapper->SetScalarModeToUseCellData();
+ surfaceMapper->SetLookupTable(lookupTable);
+ surfaceMapper->SetScalarRange(displayMinimum, displayMaximum);
+ surfaceMapper->ScalarVisibilityOn();
+
+ vtkSmartPointer surfaceActor = vtkSmartPointer::New();
+ surfaceActor->SetMapper(surfaceMapper);
+ surfaceActor->GetProperty()->EdgeVisibilityOff();
+
+ renderer->AddActor(surfaceActor);
+
+ // 叠加储层边界,并通过轻微Z偏移避免与色带表面重合.
+ if(outlinePoints.size() >= 3) {
+ vtkSmartPointer outlineVtkPoints =
+ vtkSmartPointer::New();
+ for(int i = 0; i < outlinePoints.size(); ++i) {
+ outlineVtkPoints->InsertNextPoint(outlinePoints[i].x(),
+ outlinePoints[i].y(), 0.01);
+ }
+
+ vtkSmartPointer outlineLines =
+ vtkSmartPointer::New();
+ outlineLines->InsertNextCell(outlinePoints.size() + 1);
+ for(int i = 0; i < outlinePoints.size(); ++i) {
+ outlineLines->InsertCellPoint(i);
+ }
+ outlineLines->InsertCellPoint(0);
+
+ vtkSmartPointer outlineData =
+ vtkSmartPointer::New();
+ outlineData->SetPoints(outlineVtkPoints);
+ outlineData->SetLines(outlineLines);
+
+ vtkSmartPointer outlineMapper =
+ vtkSmartPointer::New();
+ outlineMapper->SetInputData(outlineData);
+ outlineMapper->ScalarVisibilityOff();
+
+ vtkSmartPointer outlineActor = vtkSmartPointer::New();
+ outlineActor->SetMapper(outlineMapper);
+ outlineActor->GetProperty()->SetColor(0.55, 0.38, 0.22);
+ outlineActor->GetProperty()->SetLineWidth(1.2);
+ renderer->AddActor(outlineActor);
+ }
+
+ // 测点和数值标签复用同一组坐标和值,叠加显示在插值面上.
+ if((showMeasurementPoints || showMeasurementLabels) &&
+ !measurementPoints.isEmpty() &&
+ measurementPoints.size() == measurementValues.size()) {
+ vtkSmartPointer measurementVtkPoints =
+ vtkSmartPointer::New();
+ vtkSmartPointer measurementScalars =
+ vtkSmartPointer::New();
+ measurementScalars->SetName("MeasurementValue");
+ measurementScalars->SetNumberOfComponents(1);
+
+ for(int i = 0; i < measurementPoints.size(); ++i) {
+ measurementVtkPoints->InsertNextPoint(measurementPoints[i].x(),
+ measurementPoints[i].y(), 0.02);
+ measurementScalars->InsertNextValue(measurementValues[i]);
+ }
+
+ vtkSmartPointer measurementData =
+ vtkSmartPointer::New();
+ measurementData->SetPoints(measurementVtkPoints);
+ measurementData->GetPointData()->SetScalars(measurementScalars);
+
+ if(showMeasurementPoints) {
+ vtkSmartPointer glyphFilter =
+ vtkSmartPointer::New();
+ glyphFilter->SetInputData(measurementData);
+
+ // 深色外层形成清晰描边,避免测点颜色与附近插值色带融为一体.
+ vtkSmartPointer borderMapper =
+ vtkSmartPointer::New();
+ borderMapper->SetInputConnection(glyphFilter->GetOutputPort());
+ borderMapper->ScalarVisibilityOff();
+
+ vtkSmartPointer borderActor =
+ vtkSmartPointer::New();
+ borderActor->SetMapper(borderMapper);
+ borderActor->GetProperty()->SetColor(0.10, 0.10, 0.10);
+ borderActor->GetProperty()->SetPointSize(9.0);
+ renderer->AddActor(borderActor);
+
+ vtkSmartPointer measurementMapper =
+ vtkSmartPointer::New();
+ measurementMapper->SetInputConnection(glyphFilter->GetOutputPort());
+ measurementMapper->SetLookupTable(lookupTable);
+ measurementMapper->SetScalarRange(displayMinimum, displayMaximum);
+ measurementMapper->SetScalarModeToUsePointData();
+
+ vtkSmartPointer measurementActor =
+ vtkSmartPointer::New();
+ measurementActor->SetMapper(measurementMapper);
+ measurementActor->GetProperty()->SetPointSize(5.0);
+ measurementActor->SetPosition(0.0, 0.0, 0.001);
+ renderer->AddActor(measurementActor);
+ }
+
+ if(showMeasurementLabels) {
+ // 标签使用独立坐标上移,测点方框仍保持在原始测量位置.
+ const double labelOffset =
+ qMax(bounds.width(), bounds.height()) * 0.018;
+ vtkSmartPointer measurementLabelPoints =
+ vtkSmartPointer::New();
+ for(int i = 0; i < measurementPoints.size(); ++i) {
+ measurementLabelPoints->InsertNextPoint(
+ measurementPoints[i].x(),
+ measurementPoints[i].y() + labelOffset, 0.03);
+ }
+
+ vtkSmartPointer