Set 1: Environment & Resources
Set 2: Education & Technology
Set 3: Health & Lifestyle
Set 4: Society & Culture
Set 5: Work & Career
Set 6: Cities & Architecture
Set 7: Economics & Business
Set 8: Crime & Justice
Set 9: Media & Communication
Set 10: Science & Research
60:00
// Initialize dark mode
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
document.documentElement.classList.add('dark');
}
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', event => {
if (event.matches) {
document.documentElement.classList.add('dark');
} else {
document.documentElement.classList.remove('dark');
}
});
// Test data with 10 sets of IELTS Writing tasks
const testQuestionSets = [
// Set 1: Environment & Resources
{
name: "Environment & Resources",
tasks: [
{
type: "Task 1",
instruction: "The graph below shows global carbon dioxide emissions from 1970 to 2020 by region. Summarize the information by selecting and reporting the main features, and make comparisons where relevant.",
chartType: "lineChart",
chartData: {
title: "Global COâ‚‚ Emissions by Region (1970-2020)",
xAxis: ["1970", "1980", "1990", "2000", "2010", "2020"],
yAxisTitle: "COâ‚‚ Emissions (Billion Tonnes)",
series: [
{name: "North America", data: [6.0, 6.5, 6.8, 7.5, 7.0, 5.8], color: "#1f77b4"},
{name: "Europe", data: [5.7, 5.5, 5.1, 5.0, 4.8, 4.0], color: "#ff7f0e"},
{name: "Asia", data: [2.1, 3.2, 5.0, 7.0, 11.2, 14.5], color: "#2ca02c"},
{name: "Africa", data: [0.5, 0.8, 1.0, 1.2, 1.5, 1.8], color: "#d62728"},
{name: "South America", data: [0.4, 0.7, 0.9, 1.3, 1.6, 1.7], color: "#9467bd"}
]
},
wordCount: 150,
timeLimit: 20
},
{
type: "Task 2",
instruction: "Some people believe that protecting the environment should be the top priority for governments, even if it means slower economic development. Others argue that economic growth should be prioritized. Discuss both these views and give your own opinion.",
wordCount: 250,
timeLimit: 40
}
]
},
// Set 2: Education & Technology
{
name: "Education & Technology",
tasks: [
{
type: "Task 1",
instruction: "The table below shows the percentage of university students who used different types of digital learning resources in 2010 and 2020. Summarize the information by selecting and reporting the main features, and make comparisons where relevant.",
chartType: "table",
chartData: {
title: "University Students' Use of Digital Learning Resources (%)",
headers: ["Resource Type", "2010", "2020", "Change"],
rows: [
["Digital textbooks", "32%", "78%", "+46%"],
["Online video lectures", "24%", "89%", "+65%"],
["Mobile learning apps", "11%", "73%", "+62%"],
["Online discussion forums", "38%", "67%", "+29%"],
["Virtual simulations", "14%", "51%", "+37%"],
["AI-based tutoring tools", "5%", "42%", "+37%"]
]
},
wordCount: 150,
timeLimit: 20
},
{
type: "Task 2",
instruction: "In many countries, online education is becoming increasingly popular. Some people believe traditional classroom learning will eventually be replaced by online learning. To what extent do you agree or disagree with this view?",
wordCount: 250,
timeLimit: 40
}
]
},
// Set 3: Health & Lifestyle
{
name: "Health & Lifestyle",
tasks: [
{
type: "Task 1",
instruction: "The diagrams below show the process of how yoga practice affects the human body and mind. Summarize the information by selecting and reporting the main features, and make comparisons where relevant.",
chartType: "processChart",
chartData: {
title: "How Yoga Practice Affects Body and Mind",
steps: [
{
title: "Initial Practice",
description: "Regular breathing exercises and physical poses",
effects: ["Increased oxygen intake", "Improved flexibility", "Enhanced focus"]
},
{
title: "Short-term Effects",
description: "After 2-4 weeks of regular practice",
effects: ["Reduced stress hormones", "Better posture", "Improved sleep quality"]
},
{
title: "Medium-term Effects",
description: "After 2-6 months of practice",
effects: ["Lower blood pressure", "Increased muscle strength", "Better concentration"]
},
{
title: "Long-term Effects",
description: "After 1+ year of consistent practice",
effects: ["Structural improvements in brain", "Enhanced immune function", "Improved emotional regulation"]
}
]
},
wordCount: 150,
timeLimit: 20
},
{
type: "Task 2",
instruction: "Some people believe that the government should be responsible for improving public health, while others think individuals should take care of their own health. Discuss both views and give your opinion.",
wordCount: 250,
timeLimit: 40
}
]
},
// Set 4: Society & Culture
{
name: "Society & Culture",
tasks: [
{
type: "Task 1",
instruction: "The charts below show the average time spent on different leisure activities by people in a European country in 1990 and 2020. Summarize the information by selecting and reporting the main features, and make comparisons where relevant.",
chartType: "barChart",
chartData: {
title: "Average Weekly Hours Spent on Leisure Activities",
categories: ["Watching TV", "Social media", "Reading", "Exercise", "Socializing", "Hobbies"],
series: [
{name: "1990", data: [18, 0, 7, 4, 8, 6], color: "#5470c6"},
{name: "2020", data: [12, 14, 3, 5, 5, 4], color: "#91cc75"}
],
yAxisTitle: "Hours per week"
},
wordCount: 150,
timeLimit: 20
},
{
type: "Task 2",
instruction: "In many countries, traditional cultural practices are being lost as people adopt more globalized lifestyles. Is this a positive or negative development?",
wordCount: 250,
timeLimit: 40
}
]
},
// Set 5: Work & Career
{
name: "Work & Career",
tasks: [
{
type: "Task 1",
instruction: "The pie charts below show the percentages of different job types in a developed country in 2000 and 2020. Summarize the information by selecting and reporting the main features, and make comparisons where relevant.",
chartType: "pieChart",
chartData: {
title: "Distribution of Job Types (2000 vs 2020)",
charts: [
{
title: "2000",
data: [
{name: "Manufacturing", value: 28, color: "#5470c6"},
{name: "Services", value: 42, color: "#91cc75"},
{name: "Technology", value: 12, color: "#fac858"},
{name: "Agriculture", value: 8, color: "#ee6666"},
{name: "Other", value: 10, color: "#73c0de"}
]
},
{
title: "2020",
data: [
{name: "Manufacturing", value: 15, color: "#5470c6"},
{name: "Services", value: 48, color: "#91cc75"},
{name: "Technology", value: 26, color: "#fac858"},
{name: "Agriculture", value: 4, color: "#ee6666"},
{name: "Other", value: 7, color: "#73c0de"}
]
}
]
},
wordCount: 150,
timeLimit: 20
},
{
type: "Task 2",
instruction: "Some people believe that having a job with a high salary is more important than job satisfaction. To what extent do you agree or disagree?",
wordCount: 250,
timeLimit: 40
}
]
},
// Set 6: Cities & Architecture
{
name: "Cities & Architecture",
tasks: [
{
type: "Task 1",
instruction: "The maps below show the development of a small town between 1980 and 2020. Summarize the information by selecting and reporting the main features, and make comparisons where relevant.",
chartType: "map",
chartData: {
title: "Town Development: 1980 vs 2020",
description: "The maps show the transformation of Riverdale town over a 40-year period, with significant expansion of urban areas, new transportation infrastructure, and conversion of agricultural land to residential and commercial use."
},
wordCount: 150,
timeLimit: 20
},
{
type: "Task 2",
instruction: "As cities continue to grow, many governments are struggling to provide adequate housing for their populations. What are the causes of urban housing problems and what solutions could be implemented?",
wordCount: 250,
timeLimit: 40
}
]
},
// Set 7: Economics & Business
{
name: "Economics & Business",
tasks: [
{
type: "Task 1",
instruction: "The chart below shows the percentage of small businesses that failed within five years of starting, across different industries in a developed economy. Summarize the information by selecting and reporting the main features, and make comparisons where relevant.",
chartType: "horizontalBarChart",
chartData: {
title: "Small Business Failure Rates by Industry (Within 5 Years)",
categories: ["Restaurants", "Retail", "Construction", "Technology", "Healthcare", "Professional Services", "Manufacturing"],
data: [60, 53, 48, 63, 38, 41, 49],
xAxisTitle: "Failure Rate (%)"
},
wordCount: 150,
timeLimit: 20
},
{
type: "Task 2",
instruction: "Some people believe that governments should provide financial support to artists such as painters, musicians and poets. Others believe that artists should be funded by alternative sources. Discuss both views and give your opinion.",
wordCount: 250,
timeLimit: 40
}
]
},
// Set 8: Crime & Justice
{
name: "Crime & Justice",
tasks: [
{
type: "Task 1",
instruction: "The graphs below show the number of reported crimes per 100,000 people in a developed country from 2000 to 2020, divided into different categories. Summarize the information by selecting and reporting the main features, and make comparisons where relevant.",
chartType: "lineChart",
chartData: {
title: "Crime Rates per 100,000 Population (2000-2020)",
xAxis: ["2000", "2005", "2010", "2015", "2020"],
yAxisTitle: "Number of crimes per 100,000 population",
series: [
{name: "Violent crimes", data: [450, 425, 410, 380, 360], color: "#c23531"},
{name: "Property crimes", data: [3200, 2800, 2400, 2100, 1800], color: "#2f4554"},
{name: "Fraud", data: [200, 280, 420, 650, 820], color: "#61a0a8"},
{name: "Cyber crimes", data: [50, 120, 280, 560, 910], color: "#d48265"}
]
},
wordCount: 150,
timeLimit: 20
},
{
type: "Task 2",
instruction: "Some people believe that the best way to reduce crime is to give longer prison sentences. Others, however, believe there are better alternative ways of reducing crime. Discuss both these views and give your own opinion.",
wordCount: 250,
timeLimit: 40
}
]
},
// Set 9: Media & Communication
{
name: "Media & Communication",
tasks: [
{
type: "Task 1",
instruction: "The diagrams below show how people received news in 1990 and 2020. Summarize the information by selecting and reporting the main features, and make comparisons where relevant.",
chartType: "pieChart",
chartData: {
title: "News Consumption Sources (1990 vs 2020)",
charts: [
{
title: "1990",
data: [
{name: "Television", value: 45, color: "#5470c6"},
{name: "Newspapers", value: 35, color: "#91cc75"},
{name: "Radio", value: 18, color: "#fac858"},
{name: "Internet", value: 2, color: "#ee6666"}
]
},
{
title: "2020",
data: [
{name: "Television", value: 26, color: "#5470c6"},
{name: "Newspapers", value: 8, color: "#91cc75"},
{name: "Radio", value: 6, color: "#fac858"},
{name: "Internet", value: 45, color: "#ee6666"},
{name: "Social Media", value: 15, color: "#73c0de"}
]
}
]
},
wordCount: 150,
timeLimit: 20
},
{
type: "Task 2",
instruction: "The Internet has transformed the way information is shared and consumed. While some argue this has improved the world, others feel these changes have had negative consequences. Discuss both views and give your opinion.",
wordCount: 250,
timeLimit: 40
}
]
},
// Set 10: Science & Research
{
name: "Science & Research",
tasks: [
{
type: "Task 1",
instruction: "The diagram below shows the process of how a new pharmaceutical drug is developed and approved. Summarize the information by selecting and reporting the main features, and make comparisons where relevant.",
chartType: "processChart",
chartData: {
title: "Pharmaceutical Drug Development Process",
steps: [
{
title: "Discovery & Research",
description: "3-6 years",
effects: ["Identify target molecules", "Develop candidate compounds", "Test in laboratory"]
},
{
title: "Preclinical Testing",
description: "1-3 years",
effects: ["Laboratory tests", "Animal testing", "Safety assessment"]
},
{
title: "Clinical Trials",
description: "6-7 years",
effects: ["Phase I: 20-100 healthy volunteers", "Phase II: 100-500 patient volunteers", "Phase III: 1,000-5,000 patient volunteers"]
},
{
title: "FDA Review & Approval",
description: "1-2 years",
effects: ["New Drug Application (NDA) review", "Advisory committee review", "FDA decision"]
},
{
title: "Post-Marketing Surveillance",
description: "Ongoing",
effects: ["Monitor for side effects", "Additional studies", "Potential label changes"]
}
]
},
wordCount: 150,
timeLimit: 20
},
{
type: "Task 2",
instruction: "Scientific research should be carried out and controlled by governments rather than private companies. To what extent do you agree or disagree with this opinion?",
wordCount: 250,
timeLimit: 40
}
]
}
];
let currentSetIndex = 0;
let currentTaskIndex = 0;
let timerInterval;
let timeRemaining = 3600; // 60 minutes in seconds
let testInProgress = false;
let responses = {
task1: "",
task2: ""
};
// DOM Elements
const testContent = document.getElementById('testContent');
const startButton = document.getElementById('startButton');
const endButton = document.getElementById('endButton');
const timerDisplay = document.getElementById('timerDisplay');
const testSelector = document.getElementById('testSelector');
// Update question set when selector changes
testSelector.addEventListener('change', function() {
currentSetIndex = parseInt(this.value);
resetTest();
displayWelcomeMessage();
});
// Format time for display (mm:ss)
function formatTime(seconds) {
const minutes = Math.floor(seconds / 60);
const remainingSeconds = seconds % 60;
return `${minutes}:${remainingSeconds < 10 ? '0' : ''}${remainingSeconds}`;
}
// Update timer display
function updateTimer() {
if (timeRemaining <= 0) {
clearInterval(timerInterval);
endTest(true);
return;
}
timeRemaining--;
timerDisplay.textContent = formatTime(timeRemaining);
// Visual indicator when time is running low
if (timeRemaining < 300) { // Less than 5 minutes
timerDisplay.classList.add('text-red-600', 'dark:text-red-400');
if (timeRemaining % 60 === 0) { // Every minute in last 5 minutes
showTimeWarning(timeRemaining / 60);
}
}
}
// Show time warning
function showTimeWarning(minutes) {
const warningMsg = document.createElement('div');
warningMsg.className = 'fixed top-4 right-4 bg-red-100 dark:bg-red-900 text-red-800 dark:text-red-200 px-4 py-2 rounded-lg shadow-lg transition-all duration-500 opacity-0';
warningMsg.innerHTML = `Time Alert: ${minutes} minute${minutes > 1 ? 's' : ''} remaining!`;
document.body.appendChild(warningMsg);
// Fade in
setTimeout(() => {
warningMsg.classList.replace('opacity-0', 'opacity-100');
}, 100);
// Fade out and remove
setTimeout(() => {
warningMsg.classList.replace('opacity-100', 'opacity-0');
setTimeout(() => {
document.body.removeChild(warningMsg);
}, 500);
}, 5000);
}
// Reset test to beginning
function resetTest() {
currentTaskIndex = 0;
testInProgress = false;
timeRemaining = 3600; // Reset to 60 minutes
timerDisplay.textContent = formatTime(timeRemaining);
timerDisplay.classList.remove('text-red-600', 'dark:text-red-400');
if (timerInterval) {
clearInterval(timerInterval);
timerInterval = null;
}
responses = {
task1: "",
task2: ""
};
startButton.textContent = 'Start';
startButton.classList.remove('bg-red-500', 'hover:bg-red-600');
startButton.classList.add('bg-primary', 'hover:bg-blue-600');
}
// Start test
function startTest() {
testInProgress = true;
startButton.textContent = 'Pause';
// Initialize timer
if (!timerInterval) {
timerInterval = setInterval(updateTimer, 1000);
}
// Display tasks
displayTasks();
}
// Pause test
function pauseTest() {
testInProgress = false;
startButton.textContent = 'Resume';
if (timerInterval) {
clearInterval(timerInterval);
timerInterval = null;
}
}
// End test
function endTest(timeExpired = false) {
testInProgress = false;
if (timerInterval) {
clearInterval(timerInterval);
timerInterval = null;
}
// Save any unsaved responses
const task1Textarea = document.getElementById('task1-response');
const task2Textarea = document.getElementById('task2-response');
if (task1Textarea) {
responses.task1 = task1Textarea.value;
}
if (task2Textarea) {
responses.task2 = task2Textarea.value;
}
// Show completed message and results
let completionMessage = timeExpired ?
'Time\'s up! Your test has been submitted.' :
'You\'ve completed the test!';
testContent.innerHTML = `
${completionMessage}
You can view your responses below and get AI evaluation of your writing.
`;
return svg;
}
// Single pie chart
let startAngle = 0;
let paths = '';
let legends = '';
data.slices.forEach((slice, i) => {
const slicePercentage = slice.value / data.slices.reduce((sum, s) => sum + s.value, 0);
const endAngle = startAngle + slicePercentage * 2 * Math.PI;
// Remaining code similar to multiple charts scenario
// ...
});
return `
${data.title}
${paths}
${legends}
`;
}
function generateTable(data) {
return `
${data.title}
${data.headers.map(header => `
${header}
`).join('')}
${data.rows.map((row, i) => `
${row.map((cell, j) => `
${cell}
`).join('')}
`).join('')}
`;
}
function generateProcessChart(data) {
return `
${data.title}
${data.steps.map((step, i) => `
${i + 1}
${step.title}
${step.description}
${step.effects.map(effect => `
${effect}
`).join('')}
${i < data.steps.length - 1 ? `
` : ''}
`).join('')}
`;
}
function generateMap(data) {
// Since we can't include external images, let's create a schematic map representation using SVG
return `
${data.title}
1980
Town Center
Town Center
Residential
Agricultural
2020
Town Center
Town Center
Residential
Industrial
Commercial
Agricultural
Park
${data.description}
`;
}
// Evaluate writing response using AI
async function evaluateWriting(taskType, responseText) {
const evaluationContainer = document.getElementById(`${taskType}-evaluation`);
// Add a loading state and show container
evaluationContainer.innerHTML = `
Evaluating your writing...
`;
evaluationContainer.classList.add('show');
// Get task information
const currentSet = testQuestionSets[currentSetIndex];
const task = taskType === 'task1' ? currentSet.tasks[0] : currentSet.tasks[1];
// Prepare prompt for AI
const systemPrompt = `
You are an IELTS writing examiner with extensive experience. Evaluate the candidate's response for an IELTS ${task.type}.
The task was: "${task.instruction}"
Provide band scores (0-9, can use half bands like 6.5) and detailed comments for each of these criteria:
1. Task Achievement/Response: How well the candidate addresses all parts of the task with a fully developed position.
2. Coherence and Cohesion: How well the information and ideas are organized, using paragraphs and cohesive devices.
3. Lexical Resource: The range and precision of vocabulary used.
4. Grammatical Range and Accuracy: The range and accuracy of grammar used.
Then provide an overall band score and 2-3 sentences of constructive feedback on how to improve.
Only return a JSON object with this structure:
{
"taskAchievement": {"score": 0.0, "comment": ""},
"coherence": {"score": 0.0, "comment": ""},
"lexical": {"score": 0.0, "comment": ""},
"grammar": {"score": 0.0, "comment": ""},
"overall": 0.0,
"feedback": ""
}
`;
try {
// Use direct API call to OpenRouter
const response = await fetch("https://openrouter.ai/api/v1/chat/completions", {
method: "POST",
headers: {
"Authorization": "Bearer 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",
"HTTP-Referer": window.location.href,
"X-Title": "IELTS Writing Mock Test",
"Content-Type": "application/json"
},
body: JSON.stringify({
"model": "qwen/qwen-2-7b-instruct:free",
"messages": [
{ role: "system", content: systemPrompt },
{ role: "user", content: `Candidate's response for IELTS ${task.type}: ${responseText}` }
]
})
});
const data = await response.json();
if (!data || !data.choices || !data.choices[0] || !data.choices[0].message) {
throw new Error("Invalid response from API");
}
const content = data.choices[0].message.content;
try {
// Try to parse the response as JSON
let evaluation;
// Extract JSON from message content
const jsonMatch = content.match(/{[\s\S]*}/);
if (jsonMatch) {
evaluation = JSON.parse(jsonMatch[0]);
} else {
throw new Error("Could not parse evaluation JSON from response");
}
displayEvaluation(evaluation, evaluationContainer);
} catch (error) {
console.error('Error parsing evaluation:', error);
evaluationContainer.innerHTML = `
`;
}
}
// Display evaluation results
function displayEvaluation(evaluation, container) {
// Map scores to colors
function getScoreColor(score) {
if (score >= 8) return 'text-green-600 dark:text-green-400';
if (score >= 6.5) return 'text-blue-600 dark:text-blue-400';
if (score >= 5) return 'text-yellow-600 dark:text-yellow-400';
return 'text-red-600 dark:text-red-400';
}
container.innerHTML = `
IELTS Writing Evaluation
Task Achievement
${evaluation.taskAchievement.score}
${evaluation.taskAchievement.comment}
Coherence & Cohesion
${evaluation.coherence.score}
${evaluation.coherence.comment}
Lexical Resource
${evaluation.lexical.score}
${evaluation.lexical.comment}
Grammatical Range & Accuracy
${evaluation.grammar.score}
${evaluation.grammar.comment}
Overall Band Score
${evaluation.overall}
${evaluation.feedback}
`;
}
// Rewrite response using AI
async function rewriteResponse(taskType, responseText) {
const evaluationContainer = document.getElementById(`${taskType}-evaluation`);
// Add a loading state and show container
evaluationContainer.innerHTML = `
Improving your writing...
`;
evaluationContainer.classList.add('show');
// Get task information
const currentSet = testQuestionSets[currentSetIndex];
const task = taskType === 'task1' ? currentSet.tasks[0] : currentSet.tasks[1];
try {
// Prepare prompt for AI
const systemPrompt = `
You are an IELTS writing expert who helps candidates improve their writing.
Please improve the following IELTS ${task.type} response, making it more coherent, sophisticated, and accurate.
Ensure it fully addresses the task: "${task.instruction}".
Keep the same core ideas but enhance the vocabulary, grammar, and organization to achieve a band 8+ level.
Only return the improved response directly, with no explanations or comments.
`;
// Use direct API call to OpenRouter
const response = await fetch("https://openrouter.ai/api/v1/chat/completions", {
method: "POST",
headers: {
"Authorization": "Bearer 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",
"HTTP-Referer": window.location.href,
"X-Title": "IELTS Writing Mock Test",
"Content-Type": "application/json"
},
body: JSON.stringify({
"model": "qwen/qwen-2-7b-instruct:free",
"messages": [
{ role: "system", content: systemPrompt },
{ role: "user", content: responseText }
]
})
});
const data = await response.json();
if (!data || !data.choices || !data.choices[0] || !data.choices[0].message) {
throw new Error("Invalid response from API");
}
const improvedText = data.choices[0].message.content;
evaluationContainer.innerHTML = `
Task 1: Analyzing visual information (20 minutes, 150+ words)
Task 2: Essay writing (40 minutes, 250+ words)
You will have 60 minutes to complete both tasks. Your time will begin when you click "Start".
Test Tips:
Read the instructions carefully
Plan your response before writing
Aim for at least 150 words for Task 1 and 250 words for Task 2
Leave a few minutes at the end to review your work
You can end the test early by clicking the "End" button
After completing the test, you can get AI feedback on your writing
Click "Start" when you're ready to begin the test.
`;
}
// Event listeners
startButton.addEventListener('click', function() {
if (testInProgress) {
pauseTest();
} else {
startTest();
}
});
endButton.addEventListener('click', function() {
if (confirm('Are you sure you want to end the test? This will submit your current responses.')) {
endTest();
}
});
// Initialize with welcome message
window.addEventListener('load', function() {
displayWelcomeMessage();
});