From 18c38b020ec89d3ec1b5f368bcfe916e924c09ea Mon Sep 17 00:00:00 2001 From: xupei Date: Tue, 26 Aug 2025 23:53:40 +0800 Subject: [PATCH] =?UTF-8?q?TASK:=E9=BB=98=E8=AE=A4=E7=A7=AF=E5=88=86?= =?UTF-8?q?=E5=88=86=E9=85=8D=E6=94=B9=E4=B8=BA=E5=B9=B3=E5=9D=87=E5=88=86?= =?UTF-8?q?=E9=85=8D=EF=BC=9B=E8=B6=85=E7=BA=A7=E7=AE=A1=E7=90=86=E5=91=98?= =?UTF-8?q?=E5=8F=AF=E6=96=B0=E5=A2=9E=E6=95=99=E8=82=B2=E3=80=81=E4=BC=81?= =?UTF-8?q?=E4=B8=9A=E7=AE=A1=E7=90=86=E5=91=98=E8=B4=A6=E6=88=B7=EF=BC=9B?= =?UTF-8?q?=E7=BB=84=E7=BB=87=E6=88=90=E5=91=98=E4=BD=BF=E7=94=A8=E7=A7=AF?= =?UTF-8?q?=E5=88=86=E6=97=B6=E9=9C=80=E8=A6=81=E8=AE=B0=E5=BD=95creditsUs?= =?UTF-8?q?age=EF=BC=9B=E8=AF=95=E7=94=A8=E7=94=A8=E6=88=B7=E5=88=9D?= =?UTF-8?q?=E5=A7=8B50=E7=A7=AF=E5=88=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/da/controller/AccountController.java | 8 +- .../com/ai/da/model/dto/AccountAddDTO.java | 14 +++ .../com/ai/da/service/AccountService.java | 4 +- .../com/ai/da/service/CreditsService.java | 4 - .../da/service/impl/AccountServiceImpl.java | 89 ++++++++++-------- .../impl/ConvenientInquiryServiceImpl.java | 36 ++++++- .../da/service/impl/CreditsServiceImpl.java | 53 ++--------- .../da/service/impl/GenerateServiceImpl.java | 10 +- .../files/sub_account_import_template.xlsx | Bin 11044 -> 11262 bytes 9 files changed, 121 insertions(+), 97 deletions(-) diff --git a/src/main/java/com/ai/da/controller/AccountController.java b/src/main/java/com/ai/da/controller/AccountController.java index fdb35151..0300aca0 100644 --- a/src/main/java/com/ai/da/controller/AccountController.java +++ b/src/main/java/com/ai/da/controller/AccountController.java @@ -182,21 +182,21 @@ public class AccountController { * 填写调查问卷 * @return */ - @ApiOperation(value = "填写调查问卷") +/* @ApiOperation(value = "填写调查问卷") @PostMapping("/questionnaire") public Response questionnaire(@Valid @RequestBody String questionnaireInfo){ return Response.success(accountService.collectQuestionnaires(questionnaireInfo)); - } + }*/ /** * 参与活动 获取福利 * @return */ - @ApiOperation(value = "参与活动 获取福利") +/* @ApiOperation(value = "参与活动 获取福利") @GetMapping("/activity") public Response getActivityBenefits(){ return Response.success(accountService.getActivityBenefits()); - } + }*/ @ApiOperation(value = "将用户账号过期时间设置为过期当天的23:59:59") @GetMapping("/setUserValidToDayEnd") diff --git a/src/main/java/com/ai/da/model/dto/AccountAddDTO.java b/src/main/java/com/ai/da/model/dto/AccountAddDTO.java index 5f054973..d23208d3 100644 --- a/src/main/java/com/ai/da/model/dto/AccountAddDTO.java +++ b/src/main/java/com/ai/da/model/dto/AccountAddDTO.java @@ -37,4 +37,18 @@ public class AccountAddDTO { private Integer systemUser; + private String organizationName; + + private Integer subAccountNum; + + public AccountAddDTO(String userEmail, String userName, String country, String validStartTime, String validEndTime, Integer isTrial, BigDecimal credits, Integer systemUser) { + this.userEmail = userEmail; + this.userName = userName; + this.country = country; + this.validStartTime = validStartTime; + this.validEndTime = validEndTime; + this.isTrial = isTrial; + this.credits = credits; + this.systemUser = systemUser; + } } diff --git a/src/main/java/com/ai/da/service/AccountService.java b/src/main/java/com/ai/da/service/AccountService.java index bc0d6c93..f0408c3a 100644 --- a/src/main/java/com/ai/da/service/AccountService.java +++ b/src/main/java/com/ai/da/service/AccountService.java @@ -16,6 +16,7 @@ import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; +import java.math.BigDecimal; import java.util.List; import java.util.Map; import java.util.Set; @@ -140,8 +141,7 @@ public interface AccountService extends IService { void moveLibraryDate(); - void updateCreditsAndEndTime(Long accountId, String value); - void updateCreditsAndEndTime(Long accountId, String value, Long endTime); + void updateCreditsAndEndTime(Long accountId, String value, Long endTime, BigDecimal creditsUsage); Boolean designWorksRegister(AccountDesignWorksRegisterDTO accountDesignWorksRegisterDTO); diff --git a/src/main/java/com/ai/da/service/CreditsService.java b/src/main/java/com/ai/da/service/CreditsService.java index fbbb9fdb..ab74883e 100644 --- a/src/main/java/com/ai/da/service/CreditsService.java +++ b/src/main/java/com/ai/da/service/CreditsService.java @@ -13,10 +13,6 @@ public interface CreditsService extends IService { Boolean buyCredits(Long accountId, Float quantity); - void creditsIncrease(Long accountId, String event); - - void creditsDecrease(Long accountId, String event); - String getCredits(Long accountId); void creditsRefund(Long accountId, Integer quantity, String orderNo); diff --git a/src/main/java/com/ai/da/service/impl/AccountServiceImpl.java b/src/main/java/com/ai/da/service/impl/AccountServiceImpl.java index 49f28f48..b0100365 100644 --- a/src/main/java/com/ai/da/service/impl/AccountServiceImpl.java +++ b/src/main/java/com/ai/da/service/impl/AccountServiceImpl.java @@ -59,6 +59,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.math.BigDecimal; +import java.math.RoundingMode; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.security.GeneralSecurityException; @@ -1145,20 +1146,21 @@ public class AccountServiceImpl extends ServiceImpl impl // 未迁移过的进行迁移,注意模特数据迁移打点信息以及转换模特格式 } - public void updateCreditsAndEndTime(Long accountId, String value) { + public void updateCreditsAndEndTime(Long accountId, String value, Long endTime, BigDecimal creditsUsage) { Account account = new Account(); account.setId(accountId); account.setCredits(new BigDecimal(value)); - accountMapper.updateById(account); - } - // todo 将其与上一个合并 - public void updateCreditsAndEndTime(Long accountId, String value, Long endTime) { - Account account = new Account(); - account.setId(accountId); - account.setCredits(new BigDecimal(value)); - if (!Objects.isNull(endTime)){ + if (Objects.nonNull(endTime)){ account.setValidEndTime(toDayEnd(endTime)); } + if (Objects.nonNull(creditsUsage)){ + // 机构的积分使用量不会超过上限 + if (creditsUsage.compareTo(account.getCreditsUsageLimit()) > 0){ + account.setCreditsUsage(account.getCreditsUsageLimit()); + } else { + account.setCreditsUsage(creditsUsage); + } + } account.setUpdateDate(new Date()); accountMapper.updateById(account); } @@ -1206,7 +1208,7 @@ public class AccountServiceImpl extends ServiceImpl impl } account.setSystemUser(3); account.setIsTrial(1); - account.setCredits(BigDecimal.valueOf(100)); + account.setCredits(BigDecimal.valueOf(50)); account.setValidEndTime(toDayEnd(Instant.now().plus(5, ChronoUnit.DAYS).toEpochMilli())); account.setIsBeginner(1); account.setValidStartTime(Instant.now().toEpochMilli()); @@ -1253,15 +1255,15 @@ public class AccountServiceImpl extends ServiceImpl impl static { HikariConfig config = new HikariConfig(); - config.setJdbcUrl("jdbc:mysql://code-create.com.hk:3306/db1nfvsgmjp3b8"); - config.setUsername("uafqtz4gsvfrw"); - config.setPassword("aida123456."); +// config.setJdbcUrl("jdbc:mysql://code-create.com.hk:3306/db1nfvsgmjp3b8"); +// config.setUsername("uafqtz4gsvfrw"); +// config.setPassword("aida123456."); // config.setJdbcUrl("jdbc:mysql://18.167.251.121:33008/aida"); // config.setUsername("aida_con"); // config.setPassword("123456"); -// config.setJdbcUrl("jdbc:mysql://localhost:3306/code-create-local?serverTimezone=UTC"); -// config.setUsername("root"); -// config.setPassword("root"); + config.setJdbcUrl("jdbc:mysql://localhost:3306/code-create-local?serverTimezone=UTC"); + config.setUsername("root"); + config.setPassword("root"); config.addDataSourceProperty("cachePrepStmts", "true"); config.addDataSourceProperty("prepStmtCacheSize", "250"); config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048"); @@ -1329,11 +1331,11 @@ public class AccountServiceImpl extends ServiceImpl impl // 不管是不是新用户 都要更新用户角色和积分 String credits = "0"; if (totalSales == 5000.0){ - log.info("年付用户,初始积分6000"); - credits = CreditsEventsEnum.INIT_MONTHLY.getValue(); + log.info("年付用户,初始积分50000"); + credits = CreditsEventsEnum.INIT_YEARLY.getValue(); systemUserType = 1; }else if (totalSales == 500.0){ - log.info("月付用户,初始积分5000"); + log.info("月付用户,初始积分3500"); credits = CreditsEventsEnum.INIT_MONTHLY.getValue(); systemUserType = 2; }else if (totalSales == 0.0){ @@ -1591,7 +1593,7 @@ public class AccountServiceImpl extends ServiceImpl impl // 3.3、更新 t_account 表 if (account.getValidEndTime() != null && account.getValidEndTime() < 1720972799000L){ - updateCreditsAndEndTime(account.getId(), added.toString(), 1720972799000L); + updateCreditsAndEndTime(account.getId(), added.toString(), 1720972799000L, null); } } @@ -1658,16 +1660,20 @@ public class AccountServiceImpl extends ServiceImpl impl // 获取该管理员的所有子账号 List subAccounts = getSubAccountsByAdmin(adminAccount); - if (CollectionUtils.isEmpty(subAccounts)) { + if (CollectionUtils.isEmpty(subAccounts) + || Objects.isNull(adminAccount.getSubAccountNum()) + || adminAccount.getSubAccountNum() == 0) { log.debug("管理员 {} 没有子账号", adminAccount.getId()); continue; } + BigDecimal averageCredits = adminAccount.getCreditsUsageLimit().divide(new BigDecimal(adminAccount.getSubAccountNum()), RoundingMode.FLOOR); + // 批量更新子账号积分 - int processedCount = batchUpdateSubAccountsCredits(subAccounts); + int processedCount = batchUpdateSubAccountsCredits(subAccounts, averageCredits); totalProcessed += processedCount; - adminAccount.setCreditsUsage(new BigDecimal(3500).multiply(new BigDecimal(processedCount))); + adminAccount.setCreditsUsage(averageCredits.multiply(new BigDecimal(processedCount))); adminAccount.setCredits(adminAccount.getCreditsUsageLimit().subtract(adminAccount.getCreditsUsage())); adminAccount.setUpdateDate(new Date()); updateById(adminAccount); @@ -1696,13 +1702,13 @@ public class AccountServiceImpl extends ServiceImpl impl /** * 批量更新子账号积分 */ - private int batchUpdateSubAccountsCredits(List subAccounts) { + private int batchUpdateSubAccountsCredits(List subAccounts, BigDecimal averageCredits) { List accountsToUpdate = new ArrayList<>(); Date now = new Date(); for (Account subAcc : subAccounts) { try { - Account updatedAccount = calculateNewCredits(subAcc, now); + Account updatedAccount = calculateNewCredits(subAcc, now, averageCredits); accountsToUpdate.add(updatedAccount); } catch (Exception e) { @@ -1720,8 +1726,9 @@ public class AccountServiceImpl extends ServiceImpl impl /** * 计算新的积分值 + * 默认积分为学校总积分数 / 学校可使用子账号数 */ - private Account calculateNewCredits(Account subAcc, Date updateTime) { + private Account calculateNewCredits(Account subAcc, Date updateTime, BigDecimal averageCredits) { BigDecimal creditsUsageLimit = subAcc.getCreditsUsageLimit(); // 使用 Optional 替代 ObjectUtils.defaultIfNull BigDecimal creditsUsage = Optional.ofNullable(subAcc.getCreditsUsage()).orElse(BigDecimal.ZERO); @@ -1739,8 +1746,8 @@ public class AccountServiceImpl extends ServiceImpl impl // 确保个人积分不为负数 personalCredits = personalCredits.max(BigDecimal.ZERO); - // 新的总积分 = 个人积分 + 学校分配的新积分额度 todo 重新分配的积分是使用上个月分配的积分还是默认积分,暂时使用默认积分 3500 - BigDecimal newTotalCredits = personalCredits.add(new BigDecimal(3500)); + // 新的总积分 = 个人积分 + 学校分配的新积分额度 (重新分配的积分是使用上个月分配的积分还是默认积分,暂时使用平均积分) + BigDecimal newTotalCredits = personalCredits.add(averageCredits); // 记录积分变更日志(可选) logCreditChange(subAcc, currentCredits, newTotalCredits, creditsUsage); @@ -1750,7 +1757,7 @@ public class AccountServiceImpl extends ServiceImpl impl updatedAccount.setId(subAcc.getId()); updatedAccount.setCredits(newTotalCredits); updatedAccount.setCreditsUsage(BigDecimal.ZERO); // 重置已使用积分 - updatedAccount.setCreditsUsageLimit(new BigDecimal(3500)); // 重置为默认积分 + updatedAccount.setCreditsUsageLimit(averageCredits); // 重置为默认积分 updatedAccount.setUpdateDate(updateTime); return updatedAccount; @@ -2117,7 +2124,7 @@ public class AccountServiceImpl extends ServiceImpl impl newUser.setCreateDate(new Date()); newUser.setIsTrial(1); newUser.setIsBeginner(1); - newUser.setCredits(BigDecimal.valueOf(100)); + newUser.setCredits(BigDecimal.valueOf(50)); newUser.setSystemUser(3); accountMapper.insert(newUser); session.setAttribute("user", newUser); @@ -2424,6 +2431,7 @@ public class AccountServiceImpl extends ServiceImpl impl adminAcc.setCreditsUsage(adminAcc.getCreditsUsage().add(subAccount.getCreditsUsageLimit())); adminAcc.setCredits(adminAcc.getCreditsUsageLimit().subtract(adminAcc.getCreditsUsage())); adminAcc.setUpdateDate(new Date()); + log.debug("分配积分: remainingCredits={}, subAccId={}, setCredits={}", remainingCredits, subAccount.getId(), addSubAccountDTO.getCreditsUsageLimit()); }else { handleSubAccCredits(subAccount, adminAcc); } @@ -2457,6 +2465,7 @@ public class AccountServiceImpl extends ServiceImpl impl adminAcc.setCreditsUsage(adminAcc.getCreditsUsage().add(subAccount.getCreditsUsageLimit())); adminAcc.setCredits(adminAcc.getCreditsUsageLimit().subtract(adminAcc.getCreditsUsage())); adminAcc.setUpdateDate(new Date()); + log.debug("分配积分: remainingCredits={}, subAccId={}, setCredits={}", remainingCredits, subAccount.getId(), addSubAccountDTO.getCreditsUsageLimit()); } // 未指定积分使用上限 else { @@ -2584,8 +2593,8 @@ public class AccountServiceImpl extends ServiceImpl impl } if (Objects.nonNull(adminAcc.getCreditsUsageLimit()) && (Objects.isNull(subAcc.getCreditsUsageLimit()) || subAcc.getCreditsUsageLimit().compareTo(BigDecimal.ZERO) == 0)) { - // todo 需要先判断管理员的订阅类型 年付 -> 4200 月付 -> 3500 - BigDecimal defaultCredits = BigDecimal.valueOf(3500L); + // 默认使用平均积分 + BigDecimal defaultCredits = adminAcc.getCreditsUsageLimit().divide(new BigDecimal(adminAcc.getSubAccountNum()), RoundingMode.FLOOR);; if (remainingCredits.compareTo(defaultCredits) >= 0) { subAcc.setCreditsUsageLimit(defaultCredits); @@ -2597,7 +2606,7 @@ public class AccountServiceImpl extends ServiceImpl impl adminAcc.setCreditsUsage(adminAcc.getCreditsUsage().add(subAcc.getCreditsUsageLimit())); adminAcc.setCredits(adminAcc.getCreditsUsageLimit().subtract(adminAcc.getCreditsUsage())); adminAcc.setUpdateDate(new Date()); - log.debug("分配积分: subAccId={}, defaultCredits={}, remainingCredits={}", subAcc.getId(), defaultCredits, remainingCredits); + log.debug("分配积分: remainingCredits={}, subAccId={}, defaultCredits={}", remainingCredits, subAcc.getId(), defaultCredits); if (Objects.nonNull(subAcc.getCredits())) { subAcc.setCredits(subAcc.getCreditsUsageLimit().add(subAcc.getCredits())); @@ -2782,7 +2791,7 @@ public class AccountServiceImpl extends ServiceImpl impl newUser.setCreateDate(new Date()); newUser.setIsTrial(1); newUser.setIsBeginner(1); - newUser.setCredits(BigDecimal.valueOf(100)); + newUser.setCredits(BigDecimal.valueOf(50)); newUser.setSystemUser(3); accountMapper.insert(newUser); @@ -2886,7 +2895,7 @@ public class AccountServiceImpl extends ServiceImpl impl newUser.setCreateDate(new Date()); newUser.setIsTrial(1); newUser.setIsBeginner(1); - newUser.setCredits(BigDecimal.valueOf(100)); + newUser.setCredits(BigDecimal.valueOf(50)); newUser.setSystemUser(3); accountMapper.insert(newUser); @@ -3417,6 +3426,7 @@ public class AccountServiceImpl extends ServiceImpl impl } @Override + @Transactional public Boolean subAccountImport(MultipartFile file) { AuthPrincipalVo vo = UserContext.getUserHolder(); Account parent = accountMapper.selectById(vo.getId()); @@ -3443,14 +3453,13 @@ public class AccountServiceImpl extends ServiceImpl impl AddSubAccountDTO addSubAccountDTO = new AddSubAccountDTO(); addSubAccountDTO.setUserEmail(dto.getEmail()); + if (Objects.nonNull(dto.getCredisUsageLimit())) { + addSubAccountDTO.setCreditsUsageLimit(BigDecimal.valueOf(dto.getCredisUsageLimit())); + } addSubAccountDTO.setUserName(dto.getEmail().substring(0, dto.getEmail().indexOf("@"))); addSubAccountDTO.setUserPassword(md5(parent.getOrganizationName().toLowerCase() + "abc")); // 添加用户 - try { - addSubAccount(addSubAccountDTO); - } catch (BusinessException e){ - log.warn("批量导入业务报错, {}", e.getMsg()); - } + addSubAccount(addSubAccountDTO); } return true; diff --git a/src/main/java/com/ai/da/service/impl/ConvenientInquiryServiceImpl.java b/src/main/java/com/ai/da/service/impl/ConvenientInquiryServiceImpl.java index f71be2f9..fc481624 100644 --- a/src/main/java/com/ai/da/service/impl/ConvenientInquiryServiceImpl.java +++ b/src/main/java/com/ai/da/service/impl/ConvenientInquiryServiceImpl.java @@ -479,6 +479,15 @@ public class ConvenientInquiryServiceImpl extends ServiceImpl queryWrapper = new QueryWrapper<>(); @@ -489,8 +498,7 @@ public class ConvenientInquiryServiceImpl extends ServiceImpl i } public void doCreditsSubtract(Long accountId, CreditsEventsEnum event) { - BigDecimal existingCredits = accountService.getById(accountId).getCredits(); + Account account = accountService.getById(accountId); + BigDecimal existingCredits = account.getCredits(); BigDecimal subtract = existingCredits.subtract(new BigDecimal(event.getValue())); - accountService.updateCreditsAndEndTime(accountId, subtract.toString(), null); + BigDecimal creditsUsage = null; + if (!StringUtil.isNullOrEmpty(account.getOrganizationName())){ + creditsUsage = Objects.isNull(account.getCreditsUsage()) ? BigDecimal.ZERO : account.getCreditsUsage(); + creditsUsage = creditsUsage.add(new BigDecimal(event.getValue())); + } + accountService.updateCreditsAndEndTime(accountId, subtract.toString(), null, creditsUsage); creditsService.preInsert(accountId, event.getName(), null, Boolean.FALSE, event.getValue()); } diff --git a/src/main/resources/files/sub_account_import_template.xlsx b/src/main/resources/files/sub_account_import_template.xlsx index 67c8c351b53abf3dd54f14fbdc27c72922f4a219..a78955bc6a2829f14a525d66ece0cff155a6aaaf 100644 GIT binary patch delta 2794 zcmZ8jdpHwr8y?v-#Aqfg&+RzZ&Vxv3zoui2`~Uy} z1OSKu0081uoroYpfLBmZfHo0-wbTh0G^h)WE^6dKHjQlH7DD!?&J_Du%qG0Aj=te2 z-3ht*l5@4(&T0Ew^Vtogw-`<~)`alnR(I>V`}8;g3*#tZ^Q|%!qCP7ngVpu4bHQ8N z0pn}8OZJINtCd~^lm7OS!HGVPX*zF3%eQJG08V}pnCft>oA%Fd$oit^g5t|fbW}mr zI$7B|r)FADr{&cz@^dp6VA5^p3;UD)Yp}Uvl9H#P>mG6t>e=E%|3B=e*oYoKI~8AB(|WX*Fg=^7$-X7W)MR)yw%SC72r z+KX7a#AR+Ef%p30En*e3YHMBied|?@E9i4QavI0Up1eN41Eu|bDoK;k5Ut@*;dh_B z7{b>+U_KmjT8+=9I{*nn57^-y``$=|iMloUBugD4IO1^qEr5V`>+#0Rph$ym=vC?( z^M$TTil-7uO~e9kwcSvErPjPjK-|#eV^O{asCAD-T<}F@ebrDSCDn*4PRf4pa(Z{z z8KhNm)X&1V*cW=sx`?oxD`&7nXf<+|t9=>vo#8Jc^c@bF1Hj>J7M|8b9$F}Vp3cu7coyS6-_tXL0SsOXpamPTn!}H6Kwq2}u zE>+3QVIsFjK<~E-dpxT^>27#sN!YWY&w}D72&C5js>V4<_SYk=8#7nrzgMXAZE9j39%gPvX& zRq}2fl^24(1^Wgqno+SaAyF)?Jk#}ZGH$;Gv7fH#<)XCBdaHTOx~w#pfj70W&W>Bh zEm_Pi66Q(mjE3iTaahb9wxJ7b#X0J^>Hwnn#uK*p{85~i)eS?qyST6unv2*>miDgn z_Aue9z=u69jc_mABr(j zb%p8%B(#__%m)*l=pC|ky`Qm-6gX)@?L?yKONAbTpcR7v0%+gfVVYd*_E;KG%6sXj zM?0v%;|+D8O?Q}v?v8qPQr1^t5dM%V`2OC;F6=zsZa?GkvNLUjmL>7Tf*38plH1yW5=d3PiD= z7XCJBJy#tOMt6xgkZwLJy8RN-qc7cm7wQaan7C$AK1oulIUB$A`3`e2H-3!d6ZNAh z)`RTDe|kd_8CH+<4(U!!2vALY>%w`Hy;N#ffz07pt?JmFCGTzH?@MlZoI6mU-RMQQ zFJ*l*j01CUboZx0od_UK8BZ)cKyG%x^#i5EU!mluHbaO$Zzdmg%v@5XTduwB)?>ZZ z(U)jXdF}LdU7>=d_7Ul0K#3~_Yn+%dMF&h&V+VTQKdEUT`9tqvNlon0=o2f2sM<~7 zZz;Qqd5V$*(q6Sq?!wu&TQlf?Y%0{xli+Em=Ut{cCtlD zBJ=z9t9?kAZG4elapL~NbHkf?p0IwB&kZeW#i?@vqWe|5aoQF(2A}g=^v|2KA3l&L znr7?I;<+BPlS;8d*ALYN1FsZs)PLHMHDvZkhp*lpT5_gT={5U219!hAAh}TDF+gEvm>Z$NlitUJuxKj)ZxQF?oMs)i+wOfEJeoDEV8mT3#?#dpNNYc6~m*LmFxxoK0VI!+p>+%c;_HH6pi7Qw}{D$DmG}6yjui z>J4+Nxm}(W=GW<{n;5VQ!yV&pnYU^!7s|{uElevokvmvsY4)#+f&~_9_#X;=wjdEH z>pDH5UXCVuuDec^$N3!6n1BB~i6}IMNhr`zGmsUPO!a^8puHqK(OEh=tZ_J|->iXm z;kq}rugEsh;iTa5Gar%_dxx7pqIIO%#Q*h8TNz`%UpWH@PFFWOH$0P9?^)k8Mkgqk?-MhFYGnZBBoxExx7$b381B_<}9khAE@Os|pjb0aUo zE%Os9MetQl;Etpqs+TG$Sajy4Q?-WA2=+;x*UuZ(e8~yc!N6Rwk91({bD5McWN6gM z$G*6000t`CF18WWM;@1d0>tH+$R78etP*O*29}>1M!79sfDgN2MLNp-<5a(T{qqxQ zqFEEv?6hr4e>zTHc3eydxJZA$xw9S4+obV`R!fftFVtS{&>pt0a|Wi|#MQLmQ%QFY zR^A-lgC=TQ_nMoiulG##6K*ZvPRO+NDoV1#?3Y0#oSHCm>FN5~Xg$4^g5ttDoQ-r);RJ Kf-uNmA^!$MN)nv_ delta 2527 zcmY*bX*kq<7yetuGQ`l>w?VcU%V-(0%gziFgT}r~$re#>8YCHn8d9%B%tN+}F+7h^ zAxjb?d-i?LAlp-t*VFT%>pdUNbv~SP{m!}W`#$IQ)0ylwE@2LSK` z01y+b5gi(F)h9Ics(Q?|V6vloXf6^On@>CP`j(d$)<9Vc=+W#kWZ6+q-LfX0~mn( zwaX7bp@sF{5i;E7%6pgWa$HMMHY!?N09a~f;K}Jo_ip>=4zaQ}9&!E(jVXM^7k-^g+r~LdP+fEeRI@ajpi0gDj8Om`5 z`7{TphCW4RoKrSG&$G040Z#8~T9;ZW%uDd(|Ji!CnP521UR+Zi(VR69;ja#iUbD>q zW~Y~vNrHS~_->-e>E(alrJN7Omrm;9cU>wb1=3<<%;jN~E(lrnjl9bfk8?9Dau5%< z#?0x-j~Dp=JBIcb^~dFE5RrPsFqyiDj~N3X)!)tNENg#G7Bo$}^VKjLD|v~s|_sPh>WH{G%8FZ$XoO4GVd8xNq5&rbb=2? zE2mv!2kuQ2PUI;I);|b?@HUmc?_aM&O%hwl)AJBKKM-o%w;XUx395Y^ep8*k0bPu> zU2@B;Y0+&7M0G^YX<55~1K(7>gMO&kzn%LtrBYNxeg$>ZfLwWYUc2+JcxT+6Cc$Q< zrK9r|WrWi^RX~`K^U)PAyc7EM24*v_U9le3GHyu6=Lkk?2bf9XK(W@_C27=ddU?L5 zpzTlheD=2od|*>xz*2>{P+zkLVe<@EHZI&?m3x>9%h=?#7K+UE`Rk~k*lJ)+xi}X~ z_%wDy;c)PwAbhfHGk7o*pF}SpAav4VYf3a=`%y+`uA>c{>^wX?ns`)QX=l2n3m;Ly z)t?2`=DxL1=avlOrJuekPQ}-uH6?py6ducQ5QjL+r*OI-Xx@8xFgIYm|`vNv0wfdE3S?3JQ z&JVm6bX8!}mv>Om&GpN4vB>nH2p5=YVrgBBCiBKFhPk0way-X7%sII>T&9n!0*qU0 z5Yml{O>AKK{UX|~`3kEs?_suV^xCMCX*m1VyfNfQLUry0_vnYr2SZLjqR;f1UAO!y zIB7$e)U&XCxl=1N9M%`LJ|p$)XTVNoOxsFYpMa96`eJW!1UYiqw zVfiqTr+Hwy(~&0SJKla5eaLibywyzGypMj1) znHO8JMbI6VMPe=I4e~M*Yd5ms<#A&t5LF^FeTj?2ajr=EbgDHh_V#W|#IjtWI`dz> zZ1a2bf!iaAHz>!$4FMz%X>o#S`b5e*B;?)(XiB#04TfNZdlYHB$vw`=wSJkco4k$| ziT#f}HRk5q?H0{-`SewO5k8_S&WsyeY7<+~aBphOKN@J8E#3E(qivcd4PDbp!sD2N zuA-*Jq@nQ>qWU617djbgYP~j(Ke}(z3N~&UWofU{Rrhti8x_!Lj}Vt$8dpLWg?f%g z#rPP>A5*>0x;*O*-Hdm{Yhh{)hq`<8MBG!R;uwwNJpX7Oyj-D+9X@W~goP9-qe4jR z>9J;KR{pdN}^Qz~voF!^rT6chl>}Q=i zE1bVRkw}NG1}x534``~LE;N|AK(!AYdw^~{@gxKtjs*8LN5ayFFXbNndGmQ?ao|w? z^9$dKF1&KIW+XY7X{zC%F|=2kbyp9(mr-_y6vKRp?w?Du4=`$kdZ;yvR7X&jR+Zh< zFQhF#FYjOD&Cj2`-?n?L;mVWpMJHCQxJ`2+3lmOaPI^Y?dp2bJDJtWb z%OgBazh`f_cbfBNH71He+}fZ9*7oYcI-2f#yYJkMFns;Gb5Z$$}OO&}Ugem<~_dn5|mC^tJ