CephasAldrich commited on
Commit
f69fe96
·
verified ·
1 Parent(s): c0a1c60

Upload 6 files

Browse files
Files changed (6) hide show
  1. Dockerfile +28 -0
  2. index.css +142 -0
  3. index.html +43 -0
  4. main.js +74 -0
  5. requirements.txt +11 -0
  6. train (1).csv +0 -0
Dockerfile ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Use an official Python runtime as a parent image
2
+ FROM python:3.9-slim
3
+
4
+ # Set the working directory in the container
5
+ WORKDIR /app
6
+
7
+ # Copy the current directory contents into the container at /app
8
+ COPY . /app
9
+ # Set memory limit
10
+ ENV MALLOC_ARENA_MAX=2
11
+
12
+ # Set environment variables
13
+ ENV TRANSFORMERS_CACHE=/app/.cache/huggingface/hub
14
+ ENV NLTK_DATA=/app/nltk_data
15
+
16
+ # Create directories and set permissions
17
+ RUN mkdir -p $TRANSFORMERS_CACHE $NLTK_DATA && \
18
+ chmod -R 777 $TRANSFORMERS_CACHE $NLTK_DATA
19
+
20
+ # Install any needed packages specified in requirements.txt
21
+ RUN pip install --no-cache-dir -r requirements.txt
22
+
23
+ # Make port 7860 available to the world outside this container
24
+ EXPOSE 7860
25
+
26
+ # Run app.py when the container launches
27
+ CMD ["python", "app.py"]
28
+
index.css ADDED
@@ -0,0 +1,142 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ * {
2
+ margin: 0;
3
+ padding: 0;
4
+ box-sizing: border-box;
5
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
6
+ }
7
+
8
+ body {
9
+ background-color: #f5f5f5;
10
+ padding: 20px;
11
+ }
12
+
13
+ .container {
14
+ max-width: 1200px;
15
+ margin: 0 auto;
16
+ }
17
+
18
+ .header {
19
+ display: flex;
20
+ justify-content: space-between;
21
+ align-items: center;
22
+ margin-bottom: 20px;
23
+ }
24
+
25
+ .title {
26
+ font-size: 24px;
27
+ font-weight: bold;
28
+ color: #1a1a1a;
29
+ }
30
+
31
+ .live-badge {
32
+ background-color: #e5e7eb;
33
+ padding: 8px 12px;
34
+ border-radius: 9999px;
35
+ display: flex;
36
+ align-items: center;
37
+ gap: 6px;
38
+ font-size: 14px;
39
+ }
40
+
41
+ .stats-grid {
42
+ display: grid;
43
+ grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
44
+ gap: 20px;
45
+ margin-bottom: 20px;
46
+ }
47
+
48
+ .stat-card {
49
+ background: white;
50
+ padding: 20px;
51
+ border-radius: 8px;
52
+ box-shadow: 0 1px 3px rgba(0,0,0,0.1);
53
+ }
54
+
55
+ .stat-title {
56
+ font-size: 14px;
57
+ color: #6b7280;
58
+ margin-bottom: 8px;
59
+ }
60
+
61
+ .stat-value {
62
+ font-size: 24px;
63
+ font-weight: bold;
64
+ color: #1a1a1a;
65
+ }
66
+
67
+ .feed-container {
68
+ background: white;
69
+ border-radius: 8px;
70
+ box-shadow: 0 1px 3px rgba(0,0,0,0.1);
71
+ padding: 20px;
72
+ }
73
+
74
+ .feed-header {
75
+ display: flex;
76
+ align-items: center;
77
+ gap: 8px;
78
+ margin-bottom: 20px;
79
+ font-size: 18px;
80
+ font-weight: bold;
81
+ }
82
+
83
+ .tweet {
84
+ border: 1px solid #e5e7eb;
85
+ border-radius: 6px;
86
+ padding: 16px;
87
+ margin-bottom: 16px;
88
+ }
89
+
90
+ .tweet-header {
91
+ display: flex;
92
+ justify-content: space-between;
93
+ align-items: center;
94
+ margin-bottom: 8px;
95
+ }
96
+
97
+ .sentiment-badge {
98
+ padding: 4px 8px;
99
+ border-radius: 4px;
100
+ font-size: 12px;
101
+ font-weight: 500;
102
+ }
103
+
104
+ .sentiment-urgent {
105
+ background-color: #fee2e2;
106
+ color: #991b1b;
107
+ }
108
+
109
+ .sentiment-neutral {
110
+ background-color: #dbeafe;
111
+ color: #1e40af;
112
+ }
113
+
114
+ .sentiment-not-urgent {
115
+ background-color: #dcfce7;
116
+ color: #166534;
117
+ }
118
+
119
+ .tweet-content {
120
+ margin-bottom: 12px;
121
+ font-size: 14px;
122
+ }
123
+
124
+ .tweet-footer {
125
+ display: flex;
126
+ align-items: center;
127
+ gap: 8px;
128
+ color: #6b7280;
129
+ font-size: 12px;
130
+ }
131
+
132
+ .location {
133
+ display: flex;
134
+ align-items: center;
135
+ gap: 4px;
136
+ }
137
+
138
+ @media (max-width: 768px) {
139
+ .stats-grid {
140
+ grid-template-columns: 1fr;
141
+ }
142
+ }
index.html ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Disaster Response Monitor</title>
7
+ <link rel="stylesheet" type="text/css" href="index.css" />
8
+ </head>
9
+ <body>
10
+ <div class="container">
11
+ <div class="header">
12
+ <h1 class="title">Disaster Response Monitor</h1>
13
+ <div class="live-badge">
14
+ 📊 Live Monitoring
15
+ </div>
16
+ </div>
17
+
18
+ <div class="stats-grid">
19
+ <div class="stat-card">
20
+ <div class="stat-title">Active Disasters</div>
21
+ <div class="stat-value" id="active-disasters">0</div>
22
+ </div>
23
+ <div class="stat-card">
24
+ <div class="stat-title">Urgent Cases</div>
25
+ <div class="stat-value" id="urgent-cases">0</div>
26
+ </div>
27
+ <div class="stat-card">
28
+ <div class="stat-title">Monitored Tweets</div>
29
+ <div class="stat-value" id="total-tweets">0</div>
30
+ </div>
31
+ </div>
32
+
33
+ <div class="feed-container">
34
+ <div class="feed-header">
35
+ 💬 Disaster Reports
36
+ </div>
37
+ <div id="tweet-feed"></div>
38
+ </div>
39
+ </div>
40
+
41
+ <script src="main.js"></script>
42
+ </body>
43
+ </html>
main.js ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ let tweets = [];
2
+
3
+ function updateStats() {
4
+ document.getElementById('active-disasters').textContent =
5
+ tweets.filter(t => t.isDisaster).length;
6
+ document.getElementById('urgent-cases').textContent =
7
+ tweets.filter(t => t.sentiment === 'Urgent').length;
8
+ document.getElementById('total-tweets').textContent = tweets.length;
9
+ }
10
+
11
+ function getSentimentClass(sentiment) {
12
+ switch(sentiment) {
13
+ case 'Urgent': return 'sentiment-urgent';
14
+ case 'Neutral': return 'sentiment-neutral';
15
+ case 'Not Urgent': return 'sentiment-not-urgent';
16
+ default: return '';
17
+ }
18
+ }
19
+
20
+ function formatTimestamp(timestamp) {
21
+ return new Date(timestamp).toLocaleTimeString();
22
+ }
23
+
24
+ function renderTweets() {
25
+ const feed = document.getElementById('tweet-feed');
26
+ if (tweets.length === 0) {
27
+ feed.innerHTML = '<p>No new tweets available. This may be due to rate limiting or no recent disaster-related tweets.</p>';
28
+ } else {
29
+ feed.innerHTML = tweets.map(tweet => `
30
+ <div class="tweet">
31
+ <div class="tweet-header">
32
+ <strong>Disaster Alert</strong>
33
+ <span class="sentiment-badge ${getSentimentClass(tweet.sentiment)}">
34
+ ${tweet.sentiment.toUpperCase()}
35
+ </span>
36
+ </div>
37
+ <div class="tweet-content">
38
+ ${tweet.text}
39
+ </div>
40
+ <div class="tweet-footer">
41
+ <div class="location">
42
+ 📍 ${tweet.location}
43
+ </div>
44
+ <div style="margin-left: auto">
45
+ ${formatTimestamp(tweet.timestamp)}
46
+ </div>
47
+ </div>
48
+ </div>
49
+ `).join('');
50
+ }
51
+ }
52
+
53
+ function fetchTweets() {
54
+ fetch('/api/predict')
55
+ .then(response => response.json())
56
+ .then(data => {
57
+ if (data.error) {
58
+ console.error('Error:', data.error);
59
+ return;
60
+ }
61
+ const newTweets = JSON.parse(data.data);
62
+ tweets = [...newTweets, ...tweets].slice(0, 100); // Keep only the latest 100 tweets
63
+ updateStats();
64
+ renderTweets();
65
+ })
66
+ .catch(error => console.error('Error:', error));
67
+ }
68
+
69
+ // Fetch tweets every 5 minutes (300000 ms) instead of every 30 seconds
70
+ setInterval(fetchTweets, 300000);
71
+
72
+ // Initial fetch
73
+ fetchTweets();
74
+
requirements.txt ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ flask==2.0.1
2
+ werkzeug==2.0.1
3
+ transformers==4.30.2
4
+ nltk==3.8.1
5
+ tensorflow==2.13.0
6
+ spacy==3.6.1
7
+ gunicorn==23.0.0
8
+ tweepy==4.10.0
9
+ pandas==1.5.3
10
+ https://github.com/explosion/spacy-models/releases/download/en_core_web_sm-3.6.0/en_core_web_sm-3.6.0-py3-none-any.whl
11
+
train (1).csv ADDED
The diff for this file is too large to render. See raw diff