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 measurementLabelData = + vtkSmartPointer::New(); + measurementLabelData->SetPoints(measurementLabelPoints); + measurementLabelData->GetPointData()->SetScalars( + measurementScalars); + + vtkSmartPointer labelMapper = + vtkSmartPointer::New(); + labelMapper->SetInputData(measurementLabelData); + labelMapper->SetLabelModeToLabelScalars(); + labelMapper->SetLabelFormat("%.6g"); + labelMapper->GetLabelTextProperty()->SetColor(0.12, 0.12, 0.12); + labelMapper->GetLabelTextProperty()->SetFontSize(12); + labelMapper->GetLabelTextProperty()->BoldOff(); + labelMapper->GetLabelTextProperty()->ItalicOff(); + labelMapper->GetLabelTextProperty()->ShadowOff(); + labelMapper->GetLabelTextProperty()->SetJustificationToCentered(); + labelMapper->GetLabelTextProperty()->SetVerticalJustificationToBottom(); + + vtkSmartPointer labelActor = + vtkSmartPointer::New(); + labelActor->SetMapper(labelMapper); + renderer->AddActor2D(labelActor); + } + } + + // Map中显示的井使用独立红色标记和名称叠加,不参与插值表面计算. + if(!wellPoints.isEmpty() && wellPoints.size() == wellNames.size()) { + vtkSmartPointer wellVtkPoints = + vtkSmartPointer::New(); + vtkSmartPointer wellNameArray = + vtkSmartPointer::New(); + wellNameArray->SetName("WellName"); + for(int i = 0; i < wellPoints.size(); ++i) { + wellVtkPoints->InsertNextPoint(wellPoints[i].x(), + wellPoints[i].y(), 0.04); + wellNameArray->InsertNextValue(wellNames[i].toUtf8().constData()); + } + + vtkSmartPointer wellData = + vtkSmartPointer::New(); + wellData->SetPoints(wellVtkPoints); + wellData->GetPointData()->AddArray(wellNameArray); + + vtkSmartPointer wellGlyphFilter = + vtkSmartPointer::New(); + wellGlyphFilter->SetInputData(wellData); + + vtkSmartPointer wellBorderMapper = + vtkSmartPointer::New(); + wellBorderMapper->SetInputConnection(wellGlyphFilter->GetOutputPort()); + wellBorderMapper->ScalarVisibilityOff(); + vtkSmartPointer wellBorderActor = + vtkSmartPointer::New(); + wellBorderActor->SetMapper(wellBorderMapper); + wellBorderActor->GetProperty()->SetColor(0.12, 0.12, 0.12); + wellBorderActor->GetProperty()->SetPointSize(9.0); + renderer->AddActor(wellBorderActor); + + vtkSmartPointer wellMapper = + vtkSmartPointer::New(); + wellMapper->SetInputConnection(wellGlyphFilter->GetOutputPort()); + wellMapper->ScalarVisibilityOff(); + vtkSmartPointer wellActor = vtkSmartPointer::New(); + wellActor->SetMapper(wellMapper); + wellActor->GetProperty()->SetColor(0.90, 0.12, 0.10); + wellActor->GetProperty()->SetPointSize(5.0); + wellActor->SetPosition(0.0, 0.0, 0.001); + renderer->AddActor(wellActor); + + // 井名同样使用独立坐标,避免文字覆盖井位标记. + const double wellLabelOffset = + qMax(bounds.width(), bounds.height()) * 0.022; + vtkSmartPointer wellLabelPoints = + vtkSmartPointer::New(); + for(int i = 0; i < wellPoints.size(); ++i) { + wellLabelPoints->InsertNextPoint( + wellPoints[i].x(), + wellPoints[i].y() + wellLabelOffset, 0.05); + } + + vtkSmartPointer wellLabelData = + vtkSmartPointer::New(); + wellLabelData->SetPoints(wellLabelPoints); + wellLabelData->GetPointData()->AddArray(wellNameArray); + + vtkSmartPointer wellLabelMapper = + vtkSmartPointer::New(); + wellLabelMapper->SetInputData(wellLabelData); + wellLabelMapper->SetLabelModeToLabelFieldData(); + wellLabelMapper->SetFieldDataName("WellName"); + wellLabelMapper->SetLabelFormat("%s"); + wellLabelMapper->GetLabelTextProperty()->SetColor(0.10, 0.10, 0.10); + wellLabelMapper->GetLabelTextProperty()->SetFontSize(13); + wellLabelMapper->GetLabelTextProperty()->BoldOff(); + wellLabelMapper->GetLabelTextProperty()->ItalicOff(); + wellLabelMapper->GetLabelTextProperty()->ShadowOff(); + wellLabelMapper->GetLabelTextProperty()->SetJustificationToCentered(); + wellLabelMapper->GetLabelTextProperty()->SetVerticalJustificationToBottom(); + + vtkSmartPointer wellLabelActor = + vtkSmartPointer::New(); + wellLabelActor->SetMapper(wellLabelMapper); + renderer->AddActor2D(wellLabelActor); + } + + vtkSmartPointer scalarBar = + vtkSmartPointer::New(); + scalarBar->SetLookupTable(lookupTable); + scalarBar->SetTitle(scalarTitle.toUtf8().constData()); + scalarBar->SetNumberOfLabels(6); + scalarBar->SetPosition(0.88, 0.12); + scalarBar->SetWidth(0.08); + scalarBar->SetHeight(0.76); + scalarBar->UnconstrainedFontSizeOn(); + scalarBar->GetLabelTextProperty()->SetColor(0.15, 0.15, 0.15); + scalarBar->GetLabelTextProperty()->SetFontSize(11); + scalarBar->GetLabelTextProperty()->BoldOff(); + scalarBar->GetLabelTextProperty()->ItalicOff(); + scalarBar->GetLabelTextProperty()->ShadowOff(); + scalarBar->GetTitleTextProperty()->SetColor(0.15, 0.15, 0.15); + scalarBar->GetTitleTextProperty()->SetFontSize(13); + scalarBar->GetTitleTextProperty()->BoldOff(); + scalarBar->GetTitleTextProperty()->ItalicOff(); + scalarBar->GetTitleTextProperty()->ShadowOff(); + renderer->AddActor2D(scalarBar); + + // 使用正交相机按模型边界居中显示,保持平面比例并避免透视变形. + vtkCamera* camera = renderer->GetActiveCamera(); + const double centerX = bounds.left() + bounds.width() * 0.5; + const double centerY = bounds.top() + bounds.height() * 0.5; + camera->SetPosition(centerX, centerY, 1.0); + camera->SetFocalPoint(centerX, centerY, 0.0); + camera->SetViewUp(0.0, 1.0, 0.0); + camera->ParallelProjectionOn(); + double cameraBounds[6] = { + bounds.left(), bounds.right(), bounds.top(), bounds.bottom(), -0.1, 0.1 + }; + renderer->ResetCamera(cameraBounds); + camera->SetParallelScale(qMax(bounds.height(), bounds.width()) * 0.52); + + vtkSmartPointer interactorStyle = + vtkSmartPointer::New(); + renderWindow->GetInteractor()->SetInteractorStyle(interactorStyle); + renderWindow->Render(); +}