Skip to content

Commit 1e75bd3

Browse files
committed
Updated biggest spenders functionality
1 parent a60c0e6 commit 1e75bd3

File tree

5 files changed

+82
-13
lines changed

5 files changed

+82
-13
lines changed

src/main/java/com/redislabs/demos/redisbank/transactions/BankTransactionForwarder.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@ public void afterPropertiesSet() throws Exception {
5353

5454
@Override
5555
public void onMessage(MapRecord<String, String, String> message) {
56-
LOGGER.info("Hello message");
5756
// Update search index whenever a new transaction arrives via the stream
5857
String messageString = message.getValue().get("transaction");
5958
try {
@@ -66,6 +65,7 @@ public void onMessage(MapRecord<String, String, String> message) {
6665
// Stream message to websocket connection topic
6766
smso.convertAndSend(config.getStomp().getTransactionsTopic(), message.getValue());
6867
LOGGER.info("Streamed: {}", messageString);
68+
6969
}
7070

7171
@Override

src/main/java/com/redislabs/demos/redisbank/transactions/BankTransactionGenerator.java

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212
import java.util.Map;
1313

1414
import com.fasterxml.jackson.core.JsonProcessingException;
15-
import com.redislabs.demos.redisbank.Utilities;
1615
import com.redislabs.demos.redisbank.SerializationUtil;
16+
import com.redislabs.demos.redisbank.Utilities;
1717
import com.redislabs.lettusearch.Field;
1818
import com.redislabs.lettusearch.Field.Text.PhoneticMatcher;
1919
import com.redislabs.lettusearch.RediSearchCommands;
@@ -39,6 +39,7 @@ public class BankTransactionGenerator {
3939
private static final String ACCOUNT_INDEX = "transaction_account_idx";
4040
private static final String SEARCH_INDEX = "transaction_description_idx";
4141
private static final String BALANCE_TS = "balance_ts";
42+
private static final String SORTED_SET_KEY = "bigspenders";
4243
private final List<TransactionSource> transactionSources;
4344
private final SecureRandom random;
4445
private final DateFormat df = new SimpleDateFormat("yyyy.MM.dd 'at' HH:mm:ss");
@@ -58,6 +59,7 @@ public BankTransactionGenerator(StringRedisTemplate redis, StatefulRediSearchCon
5859
random.setSeed("lars".getBytes("UTF-8")); // Prime the RNG so it always generates the same pseudorandom set
5960

6061
createSearchIndices();
62+
deleteSortedSet();
6163
createTimeSeries();
6264
createInitialStream();
6365

@@ -84,6 +86,10 @@ private void createSearchIndices() {
8486
Field.text("transactionType").matcher(PhoneticMatcher.English).build());
8587
}
8688

89+
private void deleteSortedSet() {
90+
redis.delete(SORTED_SET_KEY);
91+
}
92+
8793
private void createTimeSeries() {
8894
redis.delete(BALANCE_TS);
8995
rts.create(BALANCE_TS, 0, null);
@@ -111,7 +117,6 @@ private void streamBankTransaction(BankTransaction bankTransaction) {
111117
transactionString = SerializationUtil.serializeObject(bankTransaction);
112118
update.put(TRANSACTION_KEY, transactionString);
113119
redis.opsForStream().add(TRANSACTIONS_STREAM, update);
114-
LOGGER.info("Update: {}", transactionString);
115120
} catch (JsonProcessingException e) {
116121
LOGGER.error("Error serialising object to JSON", e.getMessage());
117122
}
@@ -127,13 +132,13 @@ private BankTransaction createBankTransaction() {
127132
transaction.setFromAccount(Utilities.generateFakeIbanFrom(ts.getFromAccountName()));
128133
transaction.setDescription(ts.getDescription());
129134
transaction.setTransactionType(ts.getType());
130-
transaction.setAmount(createTransactionAmount());
135+
transaction.setAmount(createTransactionAmount(transaction.getFromAccountName()));
131136
transaction.setTransactionDate(df.format(new Date()));
132137
transaction.setBalanceAfter(nf.format(balance));
133138
return transaction;
134139
}
135140

136-
private String createTransactionAmount() {
141+
private String createTransactionAmount(String accountName) {
137142
Double bandwidth = (1 + random.nextInt(3)) * 100.00;
138143
Double amount = random.nextDouble() * bandwidth % 300.0;
139144
Double roundedAmount = Math.floor(amount * 100) / 100;
@@ -144,6 +149,8 @@ private String createTransactionAmount() {
144149

145150
balance = balance + roundedAmount;
146151
rts.add(BALANCE_TS, balance);
152+
redis.opsForZSet().incrementScore(SORTED_SET_KEY, accountName, roundedAmount * -1);
153+
147154
return nf.format(roundedAmount);
148155
}
149156

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package com.redislabs.demos.redisbank.transactions;
2+
3+
import lombok.Data;
4+
5+
@Data
6+
public class BiggestSpenders {
7+
8+
private final double[] series;
9+
private final String[] labels;
10+
11+
public BiggestSpenders(int size) {
12+
this.series = new double[size];
13+
this.labels = new String[size];
14+
}
15+
16+
}

src/main/java/com/redislabs/demos/redisbank/transactions/TransactionOverviewController.java

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package com.redislabs.demos.redisbank.transactions;
22

3+
import java.util.Set;
4+
35
import com.redislabs.demos.redisbank.Config;
46
import com.redislabs.demos.redisbank.Config.StompConfig;
57
import com.redislabs.demos.redisbank.UserSession;
@@ -14,6 +16,8 @@
1416
import com.redislabs.redistimeseries.RedisTimeSeries;
1517
import com.redislabs.redistimeseries.Value;
1618

19+
import org.springframework.data.redis.core.StringRedisTemplate;
20+
import org.springframework.data.redis.core.ZSetOperations.TypedTuple;
1721
import org.springframework.web.bind.annotation.CrossOrigin;
1822
import org.springframework.web.bind.annotation.GetMapping;
1923
import org.springframework.web.bind.annotation.RequestMapping;
@@ -28,18 +32,21 @@ public class TransactionOverviewController {
2832
private static final String ACCOUNT_INDEX = "transaction_account_idx";
2933
private static final String SEARCH_INDEX = "transaction_description_idx";
3034
private static final String BALANCE_TS = "balance_ts";
35+
private static final String SORTED_SET_KEY = "bigspenders";
3136

3237
private final Config config;
3338
private final UserSessionRepository userSessionRepository;
3439
private final StatefulRediSearchConnection<String, String> srsc;
3540
private final RedisTimeSeries rts;
41+
private final StringRedisTemplate redis;
3642

3743
public TransactionOverviewController(Config config, UserSessionRepository userSessionRepository,
38-
StatefulRediSearchConnection<String, String> srsc, RedisTimeSeries rts) {
44+
StatefulRediSearchConnection<String, String> srsc, RedisTimeSeries rts, StringRedisTemplate redis) {
3945
this.config = config;
4046
this.userSessionRepository = userSessionRepository;
4147
this.srsc = srsc;
4248
this.rts = rts;
49+
this.redis = redis;
4350
}
4451

4552
@GetMapping("/config/stomp")
@@ -61,6 +68,26 @@ public Balance[] listTransactionsByDate() {
6168
return balanceTs;
6269
}
6370

71+
@GetMapping("/biggestspenders")
72+
public BiggestSpenders biggestSpenders() {
73+
74+
Set<TypedTuple<String>> range = redis.opsForZSet().rangeByScoreWithScores(SORTED_SET_KEY, 0, Double.MAX_VALUE);
75+
76+
if (range.size() > 0) {
77+
BiggestSpenders biggestSpenders = new BiggestSpenders(range.size());
78+
int i = 0;
79+
for (TypedTuple<String> typedTuple : range) {
80+
biggestSpenders.getSeries()[i] = typedTuple.getScore();
81+
biggestSpenders.getLabels()[i] = typedTuple.getValue();
82+
i++;
83+
}
84+
return biggestSpenders;
85+
} else {
86+
return new BiggestSpenders(0);
87+
}
88+
89+
}
90+
6491
@GetMapping("/search")
6592
@SuppressWarnings("all")
6693
public SearchResults<String, String> searchTransactions(@RequestParam("term") String term) {

src/main/resources/static/assets/js/transactions.js

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -125,18 +125,24 @@ axios.get("/api/balance")
125125
console.log('Error! Could not reach the API. ' + error)
126126
})
127127

128-
var options = {
129-
series: [44, 55, 13, 43, 22],
128+
var pieOptions = {
129+
series: [1,2,3,4,5],
130130
chart: {
131131
height: 350,
132-
type: 'pie',
132+
type: 'donut',
133+
options: {
134+
chart: {
135+
id: "chart-id"
136+
}
137+
}
133138
},
134-
labels: ['Starbucks', 'Shell', 'BMW FS', 'Picnic', 'H&M'],
139+
labels: ['a','b','c','d','e'],
135140
responsive: [{
136141
breakpoint: 480,
137142
options: {
138143
chart: {
139-
width: 200
144+
width: 200,
145+
id: "chart-id"
140146
},
141147
legend: {
142148
position: 'bottom'
@@ -145,5 +151,18 @@ var options = {
145151
}]
146152
};
147153

148-
var chart = new ApexCharts(document.querySelector("#chart"), options);
149-
chart.render();
154+
axios.get("/api/biggestspenders")
155+
.then(function (response) {
156+
157+
pieOptions.series = response.data.series
158+
pieOptions.labels = response.data.labels
159+
160+
console.log('pieooptons', pieOptions)
161+
162+
var chart = new ApexCharts(document.querySelector("#chart"), pieOptions);
163+
chart.render()
164+
165+
})
166+
.catch(function (error) {
167+
console.log('Error! Could not reach the API. ' + error)
168+
})

0 commit comments

Comments
 (0)