Skip to content

Commit 93ec0ea

Browse files
authored
Merge pull request #180 from rwth-acis/develop
Add Gamification and priority labels
2 parents d9f667d + f6901bc commit 93ec0ea

28 files changed

+1318
-2082
lines changed

CHANGELOG.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,24 @@ the [GitHub Release Page](https://github.com/rwth-acis/RequirementsBazaar/releas
1010

1111
## [Unreleased]
1212

13+
## [0.17.0] - 2023-05-10
14+
15+
### Added
16+
17+
- Added gamification
18+
[d758be2b4a66bd943665c097eee963c65a7dc68e](https://github.com/rwth-acis/RequirementsBazaar/commit/d758be2b4a66bd943665c097eee963c65a7dc68e)
19+
- Added priority labels
20+
[#179](https://github.com/rwth-acis/RequirementsBazaar/pull/179)
21+
1322
## [0.16.0] - 2022-10-05
1423

1524
### Changed
25+
1626
- Upgraded to las2peer 1.2.3 and Java 17
1727
[#175](https://github.com/rwth-acis/RequirementsBazaar/pull/175)
1828
- Fixed bug which caused new users being unable to login
1929
[#173](https://github.com/rwth-acis/RequirementsBazaar/issues/173)
2030

21-
2231
## [0.15.0] - 2022-08-07
2332

2433
### Added

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ However you'll have to apply the migrations with liquibase manually to this data
9393

9494
The build and test process is done with gradle. A simple `gradle build` should be sufficient to build the project and run the test cases.
9595

96-
You may have to adjust either your global java environment or the one in your IDE to use Java 14 or the built asset won't start.
96+
You may have to adjust either your global java environment or the one in your IDE to use Java 17 or the built asset won't start.
9797

9898
### Debugging
9999

etc/de.rwth.dbis.acis.bazaar.service.BazaarService.properties

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,8 @@ smtpServer=
1111
emailFromAddress=
1212
emailSummaryTimePeriodInMinutes=
1313
monitor=
14+
gfBaseUrl=
15+
gfUsername=
16+
gfPassword=
17+
gfGameId=
18+
gfNamespace=

reqbaz/build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,7 @@ application {
3939
}
4040

4141
repositories {
42-
// Use JCenter for resolving dependencies.
43-
jcenter()
42+
mavenCentral()
4443

4544
// DBIS Archiva
4645
maven {
@@ -50,6 +49,7 @@ repositories {
5049

5150
dependencies {
5251
implementation 'org.jetbrains:annotations:20.1.0'
52+
implementation 'org.liquibase:liquibase-core:4.20.0'
5353

5454
// Use JUnit test framework.
5555
testImplementation 'junit:junit:4.13'

reqbaz/etc/de.rwth.dbis.acis.bazaar.service.BazaarService.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,4 @@ monitor=''
1414
twitterApiKey=
1515
twitterApiKeySecret=
1616
twitterClientId=
17-
twitterClientSecret=
17+
twitterClientSecret=

reqbaz/src/main/java/de/rwth/dbis/acis/bazaar/service/BazaarService.java

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import de.rwth.dbis.acis.bazaar.service.exception.ErrorCode;
3333
import de.rwth.dbis.acis.bazaar.service.exception.ExceptionHandler;
3434
import de.rwth.dbis.acis.bazaar.service.exception.ExceptionLocation;
35+
import de.rwth.dbis.acis.bazaar.service.gamification.GamificationManager;
3536
import de.rwth.dbis.acis.bazaar.service.internalization.Localization;
3637
import de.rwth.dbis.acis.bazaar.service.notification.ActivityDispatcher;
3738
import de.rwth.dbis.acis.bazaar.service.notification.EmailDispatcher;
@@ -52,7 +53,6 @@
5253
import i5.las2peer.restMapper.RESTService;
5354
import i5.las2peer.restMapper.annotations.ServicePath;
5455
import io.swagger.annotations.*;
55-
import lombok.Getter;
5656
import org.apache.commons.dbcp2.BasicDataSource;
5757
import org.apache.http.client.utils.URIBuilder;
5858
import org.jooq.SQLDialect;
@@ -91,6 +91,7 @@ public class BazaarService extends RESTService {
9191
private final List<BazaarFunctionRegistrar> functionRegistrar;
9292
private final NotificationDispatcher notificationDispatcher;
9393
private final TweetDispatcher tweetDispatcher;
94+
private final GamificationManager gamificationManager;
9495
private final DataSource dataSource;
9596

9697
//CONFIG PROPERTIES
@@ -111,6 +112,12 @@ public class BazaarService extends RESTService {
111112
protected String twitterClientId;
112113
protected String twitterClientSecret;
113114

115+
protected String gfBaseUrl;
116+
protected String gfUsername;
117+
protected String gfPassword;
118+
protected String gfGameId;
119+
protected String gfNamespace;
120+
114121
public BazaarService() throws Exception {
115122
setFieldValues();
116123
Locale locale = new Locale(lang, country);
@@ -166,9 +173,10 @@ public BazaarService() throws Exception {
166173
}
167174

168175
tweetDispatcher = new TweetDispatcher(this, twitterApiKey, twitterApiKeySecret, twitterClientId, twitterClientSecret);
169-
170176
new WeeklyNewProjectsTweetTask(this).schedule(timer);
171177

178+
gamificationManager = new GamificationManager(gfBaseUrl, gfUsername, gfPassword, gfGameId, gfNamespace);
179+
172180
notificationDispatcher.setBazaarService(this);
173181
}
174182

@@ -236,6 +244,10 @@ public TweetDispatcher getTweetDispatcher() {
236244
return tweetDispatcher;
237245
}
238246

247+
public GamificationManager getGamificationManager() {
248+
return gamificationManager;
249+
}
250+
239251
private void registerUserAtFirstLogin() throws Exception {
240252
Agent agent = Context.getCurrent().getMainAgent();
241253

@@ -274,6 +286,8 @@ private void registerUserAtFirstLogin() throws Exception {
274286
int userId = user.getId();
275287
// this.getNotificationDispatcher().dispatchNotification(user.getCreationDate(), Activity.ActivityAction.CREATE, MonitoringEvent.SERVICE_CUSTOM_MESSAGE_55, userId, Activity.DataType.USER, userId);
276288
dalFacade.addUserToRole(userId, "LoggedInUser", null);
289+
// add new user to gamification and game
290+
gamificationManager.initializeUser(userId);
277291
} else {
278292
// update lastLoginDate
279293
dalFacade.updateLastLoginDate(userIdByLAS2PeerId);

reqbaz/src/main/java/de/rwth/dbis/acis/bazaar/service/dal/DALFacadeImpl.java

Lines changed: 78 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ public Project createProject(Project project, int userId) throws Exception {
232232
// TODO: concurrency transaction -> https://www.jooq.org/doc/3.9/manual/sql-execution/transaction-management/
233233
addUserToRole(userId, "ProjectAdmin", newProject.getId());
234234

235-
// This is stupid, but the return value of update is inclomplete (dependent objects won't be resolved, since only the top level get by id method is called.
235+
// This is stupid, but the return value of update is incomplete (dependent objects won't be resolved, since only the top level get by id method is called).
236236
// Call repository get separately
237237
projectRepository.update(newProject);
238238
return projectRepository.findById(newProject.getId(), userId);
@@ -343,92 +343,112 @@ public Requirement modifyRequirement(Requirement modifiedRequirement, int userId
343343

344344
if (modifiedRequirement.getCategories() != null) {
345345
List<Category> oldCategories = listCategoriesByRequirementId(modifiedRequirement.getId(), userId);
346+
handleOldCategory(modifiedRequirement, oldCategories);
347+
handleNewCategory(modifiedRequirement, oldCategories);
348+
}
349+
synchronizeTags(modifiedRequirement, oldRequirement);
350+
synchronizeAttachments(modifiedRequirement, userId, oldRequirement);
351+
352+
return getRequirementById(modifiedRequirement.getId(), userId);
353+
}
354+
355+
private void handleNewCategory(Requirement modifiedRequirement, List<Category> oldCategories) throws BazaarException {
356+
for (Integer newCategory : modifiedRequirement.getCategories()) {
357+
boolean containCategory = false;
346358
for (Category oldCategory : oldCategories) {
347-
boolean containCategory = false;
348-
for (Integer newCategory : modifiedRequirement.getCategories()) {
349-
if (oldCategory.getId() == newCategory) {
350-
containCategory = true;
351-
break;
352-
}
353-
}
354-
if (!containCategory) {
355-
deleteCategoryTag(modifiedRequirement.getId(), oldCategory.getId());
359+
if (oldCategory.getId() == newCategory) {
360+
containCategory = true;
361+
break;
356362
}
357363
}
364+
if (!containCategory) {
365+
addCategoryTag(modifiedRequirement.getId(), newCategory);
366+
}
367+
}
368+
}
369+
370+
private void handleOldCategory(Requirement modifiedRequirement, List<Category> oldCategories) throws BazaarException {
371+
for (Category oldCategory : oldCategories) {
372+
boolean containCategory = false;
358373
for (Integer newCategory : modifiedRequirement.getCategories()) {
359-
boolean containCategory = false;
360-
for (Category oldCategory : oldCategories) {
361-
if (oldCategory.getId() == newCategory) {
362-
containCategory = true;
363-
break;
364-
}
365-
}
366-
if (!containCategory) {
367-
addCategoryTag(modifiedRequirement.getId(), newCategory);
374+
if (oldCategory.getId() == newCategory) {
375+
containCategory = true;
376+
break;
368377
}
369378
}
379+
if (!containCategory) {
380+
deleteCategoryTag(modifiedRequirement.getId(), oldCategory.getId());
381+
}
370382
}
383+
}
371384

372-
// Synchronize tags
373-
if (modifiedRequirement.getTags() != null) {
385+
private void synchronizeAttachments(Requirement modifiedRequirement, int userId, Requirement oldRequirement) {
386+
if (modifiedRequirement.getAttachments() != null) {
374387
// Check if tags have changed
375-
for (Tag tag : modifiedRequirement.getTags()) {
376-
try {
377-
Tag internalTag = getTagById(tag.getId());
378-
379-
// Check if tag exists (in project)
380-
if (internalTag == null || modifiedRequirement.getProjectId() != internalTag.getProjectId()) {
381-
tag.setProjectId(modifiedRequirement.getProjectId());
382-
tag = createTag(tag);
383-
}
384-
tagRequirement(tag.getId(), modifiedRequirement.getId());
385-
} catch (Exception e) {
386-
e.printStackTrace();
387-
}
388-
}
388+
checkTagChangesAttachments(modifiedRequirement, userId);
389389

390390
// Remove tags no longer present
391-
oldRequirement.getTags().stream().filter(tag -> modifiedRequirement.getTags().contains(tag)).forEach(tag -> {
391+
oldRequirement.getAttachments().stream().filter(attachment -> modifiedRequirement.getAttachments().contains(attachment)).forEach(attachment -> {
392392
try {
393-
untagRequirement(tag.getId(), oldRequirement.getId());
393+
deleteAttachmentById(attachment.getId());
394394
} catch (Exception e) {
395395
e.printStackTrace();
396396
}
397397
});
398398
}
399+
}
399400

400-
// Synchronize attachments
401-
if (modifiedRequirement.getAttachments() != null) {
402-
// Check if tags have changed
403-
for (Attachment attachment : modifiedRequirement.getAttachments()) {
404-
try {
405-
Attachment internalAttachment = null;
406-
if (attachment.getId() != 0) {
407-
internalAttachment = getAttachmentById(attachment.getId());
408-
}
409-
410-
// Check if attachment exists, otherwise create
411-
if (internalAttachment == null) {
412-
attachment.setRequirementId(modifiedRequirement.getId());
413-
attachment.setCreator(getUserById(userId));
414-
createAttachment(attachment);
415-
}
416-
} catch (Exception e) {
417-
e.printStackTrace();
401+
private void checkTagChangesAttachments(Requirement modifiedRequirement, int userId) {
402+
for (Attachment attachment : modifiedRequirement.getAttachments()) {
403+
try {
404+
Attachment internalAttachment = null;
405+
if (attachment.getId() != 0) {
406+
internalAttachment = getAttachmentById(attachment.getId());
418407
}
408+
409+
// Check if attachment exists, otherwise create
410+
if (internalAttachment == null) {
411+
attachment.setRequirementId(modifiedRequirement.getId());
412+
attachment.setCreator(getUserById(userId));
413+
createAttachment(attachment);
414+
}
415+
} catch (Exception e) {
416+
e.printStackTrace();
419417
}
418+
}
419+
}
420+
421+
private void synchronizeTags(Requirement modifiedRequirement, Requirement oldRequirement) {
422+
if (modifiedRequirement.getTags() != null) {
423+
// Check if tags have changed
424+
checkTagChanges(modifiedRequirement);
420425

421426
// Remove tags no longer present
422-
oldRequirement.getAttachments().stream().filter(attachment -> modifiedRequirement.getAttachments().contains(attachment)).forEach(attachment -> {
427+
oldRequirement.getTags().stream().filter(tag -> !modifiedRequirement.getTags().contains(tag)).forEach(tag -> {
423428
try {
424-
deleteAttachmentById(attachment.getId());
429+
untagRequirement(tag.getId(), oldRequirement.getId());
425430
} catch (Exception e) {
426431
e.printStackTrace();
427432
}
428433
});
429434
}
435+
}
430436

431-
return getRequirementById(modifiedRequirement.getId(), userId);
437+
private void checkTagChanges(Requirement modifiedRequirement) {
438+
for (Tag tag : modifiedRequirement.getTags()) {
439+
try {
440+
Tag internalTag = getTagById(tag.getId());
441+
442+
// Check if tag exists (in project)
443+
if (internalTag == null || modifiedRequirement.getProjectId() != internalTag.getProjectId()) {
444+
tag.setProjectId(modifiedRequirement.getProjectId());
445+
tag = createTag(tag);
446+
}
447+
tagRequirement(tag.getId(), modifiedRequirement.getId());
448+
} catch (Exception e) {
449+
e.printStackTrace();
450+
}
451+
}
432452
}
433453

434454
@Override

reqbaz/src/main/java/de/rwth/dbis/acis/bazaar/service/dal/entities/Dashboard.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
package de.rwth.dbis.acis.bazaar.service.dal.entities;
22

33
import com.fasterxml.jackson.annotation.JsonIgnore;
4-
import de.rwth.dbis.acis.bazaar.service.dal.helpers.UserVote;
5-
import io.swagger.annotations.ApiModelProperty;
64
import lombok.Builder;
75
import lombok.Data;
86
import lombok.EqualsAndHashCode;
97
import lombok.extern.jackson.Jacksonized;
108

119
import javax.validation.constraints.NotNull;
1210
import java.util.List;
11+
import java.util.Map;
1312

1413
@EqualsAndHashCode(callSuper = true)
1514
@Data
@@ -26,6 +25,10 @@ public class Dashboard extends EntityBase {
2625
@NotNull
2726
private List<Requirement> requirements;
2827

28+
private List<Map<String, Object>> badges;
29+
30+
private Map<String, Object> status;
31+
2932
@JsonIgnore
3033
@Override
3134
public int getId() {

reqbaz/src/main/java/de/rwth/dbis/acis/bazaar/service/dal/entities/EntityBase.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,18 @@
2525
import com.fasterxml.jackson.databind.ObjectMapper;
2626
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
2727
import de.rwth.dbis.acis.bazaar.service.dal.helpers.SerializerViews;
28+
import org.apache.commons.lang3.Validate;
29+
30+
import java.util.List;
31+
import java.util.Map;
2832

2933
/**
3034
* @since 9/16/2014
3135
*/
3236
public abstract class EntityBase implements IdentifiedById {
3337

38+
private List<Map<String, Object>> gamificationNotifications;
39+
3440
public String toJSON() throws JsonProcessingException {
3541
return new ObjectMapper().registerModule(new JavaTimeModule())
3642
.setSerializationInclusion(JsonInclude.Include.NON_NULL)
@@ -45,4 +51,14 @@ public String toPrivateJSON() throws JsonProcessingException {
4551
.writerWithView(SerializerViews.Private.class)
4652
.writeValueAsString(this);
4753
}
54+
55+
public void setGamificationNotifications(List<Map<String, Object>> gamificationNotifications) {
56+
Validate.notNull(gamificationNotifications);
57+
// prevent field to be sent if its empty
58+
this.gamificationNotifications = gamificationNotifications.size() == 0 ? null : gamificationNotifications;
59+
}
60+
61+
public List<Map<String, Object>> getGamificationNotifications() {
62+
return gamificationNotifications;
63+
}
4864
}

reqbaz/src/main/java/de/rwth/dbis/acis/bazaar/service/dal/entities/Tag.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package de.rwth.dbis.acis.bazaar.service.dal.entities;
22

3-
import com.fasterxml.jackson.annotation.JsonIgnore;
43
import lombok.Builder;
54
import lombok.Data;
65
import lombok.EqualsAndHashCode;
@@ -22,6 +21,5 @@ public class Tag extends EntityBase {
2221
@NotNull
2322
private String colour;
2423

25-
@JsonIgnore
2624
private Integer projectId;
2725
}

0 commit comments

Comments
 (0)