BLOG POST

AI 日报

120 min
Oct 9, 2025
日报 · AI · 行业观察

Apple Banned an App That Simply Archived Videos of ICE Abuses

Eyes Up's purpose is to "preserve evidence until it can be used in court." But it has been swept up in Apple's crackdown on ICE-spotting apps.

People Are Crashing Out Over Sora 2’s New Guardrails

OpenAI’s Sora 2 platform started just one week ago as an AI-generated copyright infringement free-for-all. Now, people say they’re struggling to generate anything without being hit with a violation error.

Podcast: The Final Boss of AI Slop

We talk all about Sora 2, Apple and Google removing ICE-spotting apps, and a massive update to our Flock reporting.

Cocaine in Private Jets and Sex Toys: What the FBI Found on its Secretly Backdoored Chat App

New leaked documents show how the FBI convinced a judge to let its partners collect a mass of encrypted messages from thousands of phones around the world.


Oracle-SoftBank Partner for Japan Sovereign Cloud AI Services

The two companies are teaming up to launch sovereign cloud and AI services for Japanese businesses, starting April 2025.

AI21 releases open source tiny language model

The vendor is putting its new model up against open source rivals, claiming efficiency gains of two to five times other open models.

EU Launches $1.1B Plan to Jumpstart European AI Sovereignty

The project targets various industries, including healthcare and energy. It's a response to the perception that the EU is behind on AI.

SoftBank Purchases ABB Robotics in $5.4B Deal

The deal comes as part of SoftBank's strategy to forge ahead as a leader in AI.

CoreWeave to Acquire London AI firm Monolith

The deal comes as CoreWeave expands its presence in the U.K.'s AI market.

Google's CodeMender Proactively Patches Code Vulnerabilities

CodeMender, an AI agent that automatically detects and fixes software vulnerabilities, has already patched 72 security flaws.


Does a brain-inspired network finally connect Transformers to true reasoning?

The Dragon Hatchling: The Missing Link between the Transformer and Models of the Brain


Samsung’s tiny AI model beats giant reasoning LLMs

A new paper from a Samsung AI researcher explains how a small network can beat massive Large Language Models (LLMs) in complex reasoning. In the race for AI supremacy, the industry mantra has often been “bigger is better.” Tech giants have poured billions into creating ever-larger models, but according to Alexia Jolicoeur-Martineau of Samsung SAIL […]

The post Samsung’s tiny AI model beats giant reasoning LLMs appeared first on AI News.

Tuned Global strengthens its leadership in music technology with the acquisition of Figaro.ai

The acquisition underscores Tuned Global’s commitment to shaping the future of the music industry by empowering clients with innovative technology and unmatched execution, while continuing to support existing Figaro.ai customers. Wednesday, 8 October, 2025 — Tuned Global, the leading music and media technology platform, has today announced the acquisition of Figaro.ai (by FeedForward), a London-based […]

The post Tuned Global strengthens its leadership in music technology with the acquisition of Figaro.ai appeared first on AI News.

AI Redaction That Puts Privacy First: CaseGuard Studio Leading The Way

Law enforcement, law firms, hospitals, and financial institutions are asked every day to release records, which can contain highly sensitive details – including addresses, social security numbers, medical diagnoses, evidence footage, and children’s identities. To meet compliance and security requirements, staff spend hundreds of hours manually redacting sensitive information, yet when that process goes wrong, […]

The post AI Redaction That Puts Privacy First: CaseGuard Studio Leading The Way appeared first on AI News.


To scale agentic AI, Notion tore down its tech stack and started fresh

Many organizations would be hesitant to overhaul their tech stack and start from scratch. Not Notion. For the 3.0 version of its productivity software (released in September), the company didn’t hesitate to rebuild from the ground up; they recognized that it was necessary, in fact, to support agentic AI at enterprise scale. Whereas traditional AI-powered workflows involve explicit, step-by-step instructions based on few-shot learning, AI agents powered by advanced reasoning models are thoughtful about tool definition, can identify and comprehend what tools they have at their disposal and plan next steps. “Rather than trying to retrofit into what we were building, we wanted to play to the strengths of reasoning models,” Sarah Sachs, Notion’s head of AI modeling, told VentureBeat. “We've rebuilt a new architecture because workflows are different from agents.”

Notion has been adopted by 94% of Forbes AI 50 companies, has 100 million total users and counts among its customers OpenAI, Cursor, Figma, Ramp and Vercel. In a rapidly evolving AI landscape, the company identified the need to move beyond simpler, task-based workflows to goal-oriented reasoning systems that allow agents to autonomously select, orchestrate, and execute tools across connected environments.

Very quickly, reasoning models have become “far better” at learning to use tools and follow chain-of-thought (CoT) instructions, Sachs noted. This allows them to be “far more independent” and make multiple decisions within one agentic workflow. “We rebuilt our AI system to play to that," she said. From an engineering perspective, this meant replacing rigid prompt-based flows with a unified orchestration model, Sachs explained. This core model is supported by modular sub-agents that search Notion and the web, query and add to databases and edit content. Each agent uses tools contextually; for instance, they can decide whether to search Notion itself, or another platform like Slack. The model will perform successive searches until the relevant information is found. It can then, for instance, convert notes into proposals, create follow-up messages, track tasks, and spot and make updates in knowledge bases. In Notion 2.0, the team focused on having AI perform specific tasks, which required them to “think exhaustively” about how to prompt the model, Sachs noted. However, with version 3.0, users can assign tasks to agents, and agents can actually take action and perform multiple tasks concurrently. “We reorchestrated it to be self-selecting on the tools, rather than few-shotting, which is explicitly prompting how to go through all these different scenarios,” Sachs explained. The aim is to ensure everything interfaces with AI and that “anything you can do, your Notion agent can do.”

Notion’s philosophy of “better, faster, cheaper,” drives a continuous iteration cycle that balances latency and accuracy through fine-tuned vector embeddings and elastic search optimization. Sachs’ team employs a rigorous evaluation framework that combines deterministic tests, vernacular optimization, human-annotated data and LLMs-as-a-judge, with model-based scoring identifying discrepancies and inaccuracies. “By bifurcating the evaluation, we're able to identify where the problems come from, and that helps us isolate unnecessary hallucinations,” Sachs explained. Further, making the architecture itself simpler means it’s easier to make changes as models and techniques evolve. “We optimize latency and parallel thinking as much as possible,” which leads to “way better accuracy,” Sachs noted. Models are grounded in data from the web and the Notion connected workspace. Ultimately, Sachs reported, the investment in rebuilding its architecture has already provided Notion returns in terms of capability and faster rate of change. She added, “We are fully open to rebuilding it again, when the next breakthrough happens, if we have to.”

When building and fine-tuning models, it’s important to understand that latency is subjective: AI must provide the most relevant information, not necessarily the most, at the cost of speed. “You'd be surprised at the different ways customers are willing to wait for things and not wait for things,” Sachs said. It makes for an interesting experiment: How slow can you go before people abandon the model? With pure navigational search, for instance, users may not be as patient; they want answers near-immediately. “If you ask, ‘What's two plus two,’ you don't want to wait for your agent to be searching everywhere in Slack and JIRA,” Sachs pointed out. But the longer the time it's given, the more exhaustive a reasoning agent can be. For instance, Notion can perform 20 minutes of autonomous work across hundreds of websites, files and other materials. In these instances, users are more willing to wait, Sachs explained; they allow the model to execute in the background while they attend to other tasks. “It's a product question,” said Sachs. “How do we set user expectations from the UI? How do we ascertain user expectations on latency?”

Notion understands the importance of using its own product — in fact, its employees are among its biggest power users. Sachs explained that teams have active sandboxes that generate training and evaluation data, as well as a “really active” thumbs-up-thumbs-down user feedback loop. Users aren’t shy about saying what they think should be improved or features they’d like to see. Sachs emphasized that when a user thumbs down an interaction, they are explicitly giving permission to a human annotator to analyze that interaction in a way that de-anonymizes them as much as possible. “We are using our own tool as a company all day, every day, and so we get really fast feedback loops,” said Sachs. “We’re really dogfooding our own product.” That said, it’s their own product they’re building, Sachs noted, so they understand that they may have goggles on when it comes to quality and functionality. To balance this out, Notion has trusted "very AI-savvy" design partners who are granted early access to new capabilities and provide important feedback. Sachs emphasized that this is just as important as internal prototyping. “We're all about experimenting in the open, I think you get much richer feedback,” said Sachs. “Because at the end of the day, if we just look at how Notion uses Notion, we're not really giving the best experience to our customers.” Just as importantly, continuous internal testing allows teams to evaluate progressions and make sure models aren't regressing (when accuracy and performance degrades over time). "Everything you're doing stays faithful," Sachs explained. "You know that your latency is within bounds."

Many companies make the mistake of focusing too intensely on retroactively-focused evans; this makes it difficult for them to understand how or where they're improving, Sachs pointed out. Notion considers evals as a "litmus test" of development and forward-looking progression and evals of observability and regression proofing. “I think a big mistake a lot of companies make is conflating the two,” said Sachs. “We use them for both purposes; we think about them really differently.”

For enterprises, Notion can serve as a blueprint for how to responsibly and dynamically operationalize agentic AI in a connected, permissioned enterprise workspace. Sach’s takeaways for other tech leaders:

  • Don’t be afraid to rebuild when foundational capabilities change; Notion fully re-engineered its architecture to align with reasoning-based models.

  • Treat latency as contextual: Optimize per use case, rather than universally.

  • Ground all outputs in trustworthy, curated enterprise data to ensure accuracy and trust. She advised: “Be willing to make the hard decisions. Be willing to sit at the top of the frontier, so to speak, on what you're developing to build the best product you can for your customers.”

Here’s what Jony Ive and Sam Altman revealed about their secretive AI hardware project at OpenAI’s Dev Day

In a packed theater at Fort Mason, after a whirlwind keynote of product announcements, OpenAI CEO Sam Altman sat down with Sir Jony Ive, the legendary designer behind Apple's most iconic products. The conversation, held exclusively for the 1,500 developers in attendance and not part of the public livestream, offered the clearest glimpse yet into the philosophy and ambition behind their secretive collaboration to build a new "family" of AI-powered devices.

The partnership, solidified by OpenAI's staggering $6.5 billion acquisition of Ive's hardware startup Io in May, has been the subject of intense speculation.While concrete product details remained under wraps, the discussion pivoted away from specifications and toward a profound, almost therapeutic mission: to fix our broken relationship with technology.

For nearly 45 minutes, Ive, in his signature thoughtful cadence, articulated a vision that feels like both a continuation of and a repentance for his life's work. The man who designed the iPhone, a device that arguably defined the modern era of personal computing, is now on a quest to cure the very anxieties it helped create.

The collaboration, Ive explained, was years in the making, but it was the launch of ChatGPT that provided a sudden, clarifying purpose for his post-Apple design collective, LoveFrom.

"With the launch of ChatGPT, it felt like our purpose for the last six years became clear," Ive said. "We were starting to develop some ideas for an interface based on the capability of the technology these guys were developing... I've never in my career come across anything vaguely like the affordance, like the capability that we're now starting to sense."

This capability, he argued, demands a fundamental rethinking of the devices we use, which he described as "legacy products" from a bygone era. The core motivation, he stressed, is not about corporate agendas but about a sense of duty to humanity.

"The reason we're doing this is we love our species and we want to be useful," Ive said. "We think that humanity deserves much better than humanity generally is given."

The most striking theme of the conversation was Ive's candid critique of the current state of technology — the very ecosystem he was instrumental in building. He described our current dynamic with our devices as deeply flawed, a problem he now sees AI as the solution to, not an extension of.

"I don't think we have an easy relationship with our technology at the moment," Ive began, before adding, "When I said we have an uncomfortable relationship with our technology, I mean, that's the most obscene understatement."

Instead of chasing productivity, the primary goal for this new family of devices is emotional well-being. It's a radical departure from the efficiency-obsessed ethos that dominates Silicon Valley.

When asked about his ambitions for the new devices, Ive prioritized emotional well-being over simple productivity. "I know I should care about productivity, and I do," he said, but his ultimate goal is that the tools "make us happy and fulfilled, and more peaceful and less anxious, and less disconnected."

He framed it as a chance to reject the current, fraught relationship people have with their technology. "We have a chance to... absolutely change the situation that we find ourselves in," he stated. "We don't accept this has to be the norm."

While the vision is clear, the path is fraught with challenges. Reports have surfaced about technical hurdles and philosophical debates delaying the project. Ive himself gave voice to this struggle, admitting the sheer pace of AI's progress has been overwhelming. The rapid advancement has generated a torrent of possibilities, making the crucial act of focusing incredibly difficult.

"The momentum is so extraordinary... it has led us to generate 15 to 20 really compelling product ideas. And the challenge is trying to focus," Ive confessed."I used to be good at that, and I've lost some confidence, because the choices are, it'll be easy if you really knew there were three good ones... it's just not like that."

This admission provides context to reports that the team is grappling with unresolved issues around the device's "personality" and computing infrastructure. The goal, according to one source, is to create an AI companion that is "accessible but not intrusive," avoiding the pitfalls of a "weird AI girlfriend."

While no devices were shown, the conversation and prior reports offer clues. The project involves a "family of devices," not a single gadget.It will likely be a departure from the screen-centric world we inhabit. Reports suggest a "palm-sized device without a screen" that relies on cameras and microphones to perceive its environment.

Ive argued that it would be "absurd" to assume that today's breathtaking AI technology should be delivered through "products that are decades old." The goal is to create something that feels entirely new, yet completely natural.

"It should seem inevitable. It should seem obvious, as if there wasn't possibly another rational solution to the problem," Ive said, echoing a design philosophy often attributed to his time with Steve Jobs.

He also spoke of bringing a sense of joy and whimsy back to technology, pushing back against a culture he feels has become overly serious.

"In terms of the interfaces we design, if we can't smile honestly, if it's just another deeply serious sort of exclusive thing, I think that would do us all a huge disservice," he remarked.

The chat concluded without a product reveal, leaving the audience with a philosophical blueprint rather than a technical one. The central narrative is clear: Jony Ive, the designer who put a screen in every pocket, is now betting on a screenless future, powered by OpenAI's formidable intelligence, to make us all a little less anxious and a little more human.

Samsung AI researcher's new, open reasoning model TRM outperforms models 10,000X larger — on specific problems

The trend of AI researchers developing new, small open source generative models that outperform far larger, proprietary peers continued this week with yet another staggering advancement.

Alexia Jolicoeur-Martineau, Senior AI Researcher at Samsung's Advanced​ Institute of Technology (SAIT) in Montreal, Canada,has introduced the Tiny Recursion Model (TRM) — a neural network so small it contains just 7 million parameters (internal model settings), yet it competes with or surpasses cutting-edge language models 10,000 times larger in terms of their parameter count, including OpenAI's o3-mini and Google's Gemini 2.5 Pro, on some of the toughest reasoning benchmarks in AI research.

The goal is to show that very highly performant new AI models can be created affordably without massive investments in the graphics processing units (GPUs) and power needed to train the larger, multi-trillion parameter flagship models powering many LLM chatbots today. The results were described in a research paper published on open access website arxiv.org, entitled "Less is More: Recursive Reasoning with Tiny Networks."

"The idea that one must rely on massive foundational models trained for millions of dollars by some big corporation in order to solve hard tasks is a trap," wrote Jolicoeur-Martineau on the social network X. "Currently, there is too much focus on exploiting LLMs rather than devising and expanding new lines of direction."

Jolicoeur-Martineau also added: "With recursive reasoning, it turns out that 'less is more'. A tiny model pretrained from scratch, recursing on itself and updating its answers over time, can achieve a lot without breaking the bank."

TRM's code is available now on Github under an enterprise-friendly, commercially viable MIT License — meaning anyone from researchers to companies can take, modify it, and deploy it for their own purposes, even commercial applications.

One Big Caveat

However, readers should be aware that TRM was designed specifically to perform well on structured, visual, grid-based problems like Sudoku, mazes, and puzzles on the ARC (Abstract and Reasoning Corpus)-AGI benchmark, the latter which offers tasks that should be easy for humans but difficult for AI models, such sorting colors on a grid based on a prior, but not identical, solution.

From Hierarchy to Simplicity

The TRM architecture represents a radical simplification.

It builds upon a technique called Hierarchical Reasoning Model (HRM) introduced earlier this year, which showed that small networks could tackle logical puzzles like Sudoku and mazes.

HRM relied on two cooperating networks—one operating at high frequency, the other at low—supported by biologically inspired arguments and mathematical justifications involving fixed-point theorems. Jolicoeur-Martineau found this unnecessarily complicated.

TRM strips these elements away. Instead of two networks, it uses a single two-layer model that recursively refines its own predictions.

The model begins with an embedded question and an initial answer, represented by variables x, y, and z. Through a series of reasoning steps, it updates its internal latent representation z and refines the answer y until it converges on a stable output. Each iteration corrects potential errors from the previous step, yielding a self-improving reasoning process without extra hierarchy or mathematical overhead.

How Recursion Replaces Scale

The core idea behind TRM is that recursion can substitute for depth and size.

By iteratively reasoning over its own output, the network effectively simulates a much deeper architecture without the associated memory or computational cost. This recursive cycle, run over as many as sixteen supervision steps, allows the model to make progressively better predictions — similar in spirit to how large language models use multi-step “chain-of-thought” reasoning, but achieved here with a compact, feed-forward design.

The simplicity pays off in both efficiency and generalization. The model uses fewer layers, no fixed-point approximations, and no dual-network hierarchy. A lightweight halting mechanism decides when to stop refining, preventing wasted computation while maintaining accuracy.

Performance That Punches Above Its Weight

Despite its small footprint, TRM delivers benchmark results that rival or exceed models millions of times larger. In testing, the model achieved:

  • 87.4% accuracy on Sudoku-Extreme (up from 55% for HRM)

  • 85% accuracy on Maze-Hard puzzles

  • 45% accuracy on ARC-AGI-1

  • 8% accuracy on ARC-AGI-2

These results surpass or closely match performance from several high-end large language models, including DeepSeek R1, Gemini 2.5 Pro, and o3-mini, despite TRM using less than 0.01% of their parameters.

Such results suggest that recursive reasoning, not scale, may be the key to handling abstract and combinatorial reasoning problems — domains where even top-tier generative models often stumble.

Design Philosophy: Less Is More

TRM’s success stems from deliberate minimalism. Jolicoeur-Martineau found that reducing complexity led to better generalization.

When the researcher increased layer count or model size, performance declined due to overfitting on small datasets.

By contrast, the two-layer structure, combined with recursive depth and deep supervision, achieved optimal results.

The model also performed better when self-attention was replaced with a simpler multilayer perceptron on tasks with small, fixed contexts like Sudoku.

For larger grids, such as ARC puzzles, self-attention remained valuable. These findings underline that model architecture should match data structure and scale rather than default to maximal capacity.

Training Small, Thinking Big

TRM is now officially available as open source under an MIT license on GitHub.

The repository includes full training and evaluation scripts, dataset builders for Sudoku, Maze, and ARC-AGI, and reference configurations for reproducing the published results.

It also documents compute requirements ranging from a single NVIDIA L40S GPU for Sudoku training to multi-GPU H100 setups for ARC-AGI experiments.

The open release confirms that TRM is designed specifically for structured, grid-based reasoning tasks rather than general-purpose language modeling.

Each benchmark — Sudoku-Extreme, Maze-Hard, and ARC-AGI — uses small, well-defined input–output grids, aligning with the model’s recursive supervision process.

Training involves substantial data augmentation (such as color permutations and geometric transformations), underscoring that TRM’s efficiency lies in its parameter size rather than total compute demand.

The model’s simplicity and transparency make it more accessible to researchers outside of large corporate labs. Its codebase builds directly on the earlier Hierarchical Reasoning Model framework but removes HRM’s biological analogies, multiple network hierarchies, and fixed-point dependencies.

In doing so, TRM offers a reproducible baseline for exploring recursive reasoning in small models — a counterpoint to the dominant “scale is all you need” philosophy.

Community Reaction

The release of TRM and its open-source codebase prompted an immediate debate among AI researchers and practitioners on X. While many praised the achievement, others questioned how broadly its methods could generalize.

Supporters hailed TRM as proof that small models can outperform giants, calling it “10,000× smaller yet smarter” and a potential step toward architectures that think rather than merely scale.

Critics countered that TRM’s domain is narrow — focused on bounded, grid-based puzzles — and that its compute savings come mainly from size, not total runtime.

Researcher Yunmin Cha noted that TRM’s training depends on heavy augmentation and recursive passes, “more compute, same model.”

Cancer geneticist and data scientist Chey Loveday stressed that TRM is a solver, not a chat model or text generator: it excels at structured reasoning but not open-ended language.

Machine learning researcher Sebastian Raschka positioned TRM as an important simplification of HRM rather than a new form of general intelligence.

He described its process as “a two-step loop that updates an internal reasoning state, then refines the answer.”

Several researchers, including Augustin Nabele, agreed that the model’s strength lies in its clear reasoning structure but noted that future work would need to show transfer to less-constrained problem types.

The consensus emerging online is that TRM may be narrow, but its message is broad: careful recursion, not constant expansion, could drive the next wave of reasoning research.

Looking Ahead

While TRM currently applies to supervised reasoning tasks, its recursive framework opens several future directions. Jolicoeur-Martineau has suggested exploring generative or multi-answer variants, where the model could produce multiple possible solutions rather than a single deterministic one.

Another open question involves scaling laws for recursion — determining how far the “less is more” principle can extend as model complexity or data size grows.

Ultimately, the study offers both a practical tool and a conceptual reminder: progress in AI need not depend on ever-larger models. Sometimes, teaching a small network to think carefully — and recursively — can be more powerful than making a large one think once.

AI21’s Jamba reasoning 3B redefines what 'small' means in LLMs — 250K context on a laptop

The latest addition to the small model wave for enterprises comes from AI21 Labs, which is betting that bringing models to devices will free up traffic in data centers. 

AI21’s Jamba Reasoning 3B, a “tiny” open-source model that can run extended reasoning, code generation and respond based on ground truth. Jamba Reasoning 3B handles more than 250,000 tokens and can run inference on edge devices. 

The company said Jamba Reasoning 3B works on devices such as laptops and mobile phones. 

Ori Goshen, co-CEO of AI21, told VentureBeat that the company sees more enterprise use cases for small models, mainly because moving most inference to devices frees up data centers.  

“What we're seeing right now in the industry is an economics issue where there are very expensive data center build-outs, and the revenue that is generated from the data centers versus the depreciation rate of all their chips shows the math doesn't add up,” Goshen said. 

He added that in the future “the industry by and large would be hybrid in the sense that some of the computation will be on devices locally and other inference will move to GPUs.”

Jamba Reasoning 3B combines the Mamba architecture and Transformers to allow it to run a 250K token window on devices. AI21 said it can do 2-4x faster inference speeds. Goshen said the Mamba architecture significantly contributed to the model’s speed. 

Jamba Reasoning 3B’s hybrid architecture also allows it to reduce memory requirements, thereby reducing its computing needs. 

AI21 tested the model on a standard MacBook Pro and found that it can process 35 tokens per second. 

Goshen said the model works best for tasks involving function calling, policy-grounded generation and tool routing. He said that simple requests, such as asking for information about a forthcoming meeting and asking the model to create an agenda for it, could be done on devices. The more complex reasoning tasks can be saved for GPU clusters. 

Enterprises have been interested in using a mix of small models, some of which are specifically designed for their industry and some that are condensed versions of LLMs. 

In September, Meta released MobileLLM-R1, a family of reasoning models ranging from 140M to 950M parameters. These models are designed for math, coding and scientific reasoning rather than chat applications. MobileLLM-R1 can run on compute-constrained devices. 

Google’s Gemma was one of the first small models to come to the market, designed to run on portable devices like laptops and mobile phones. Gemma has since been expanded

Companies like FICO have also begun building their own models. FICO launched its FICO Focused Language and FICO Focused Sequence small models that will only answer finance-specific questions. 

Goshen said the big difference their model offers is that it’s even smaller than most models and yet it can run reasoning tasks without sacrificing speed. 

In benchmark testing, Jamba Reasoning 3B demonstrated strong performance compared to other small models, including Qwen 4B, Meta’s Llama 3.2B-3B, and Phi-4-Mini from Microsoft

It outperformed all models on the IFBench test and Humanity’s Last Exam, although it came in second to Qwen 4 on MMLU-Pro. 

Goshen said another advantage of small models like Jamba Reasoning 3B is that they are highly steerable and provide better privacy options to enterprises because the inference is not sent to a server elsewhere. 

“I do believe there’s a world where you can optimize for the needs and the experience of the customer, and the models that will be kept on devices are a large part of it,” he said. 


OpenAI’s Trillion-Token Club Exposes Who’s Leading at AI

OpenAI

The heaviest users are established, product-heavy companies quietly embedding AI across operations.

The post OpenAI’s Trillion-Token Club Exposes Who’s Leading at AI appeared first on Analytics India Magazine.

Google Expands No-Code AI Mini-App Builder Opal to India and 14 Other Countries

Google AI Overview Changes Internet Forever, Pushes Only High-Quality Content

Alongside the expansion, Google is rolling out new features aimed at improving workflow transparency and performance. 

The post Google Expands No-Code AI Mini-App Builder Opal to India and 14 Other Countries appeared first on Analytics India Magazine.

Indian Vibe Coding Startups Have Officially Arrived

From Surat to Silicon Valley, vibe coding startups are proving that world-class AI products can be built and scaled from the home soil.

The post Indian Vibe Coding Startups Have Officially Arrived appeared first on Analytics India Magazine.

Top 10 New GCCs in India to Watch in 2025

Over 140 new greenfield GCCs have been launched across the country in the past 30 months alone, as per data shared by the Inductus Group.

The post Top 10 New GCCs in India to Watch in 2025 appeared first on Analytics India Magazine.

Moody’s India Open House: Shaping the Next Generation of Credit and Tech Talent

The event invites recent graduates, early-career professionals, and students graduating in 2025-26 to explore how data and intelligence are transforming the future of credit, risk and finance.

The post Moody’s India Open House: Shaping the Next Generation of Credit and Tech Talent appeared first on Analytics India Magazine.

Elon Musk’s xAI to Raise $20 Billion from NVIDIA and Others: Report

Elon Musk xAI Grok

NVIDIA is reportedly investing up to $2 billion in the equity part of the transaction. 

The post Elon Musk’s xAI to Raise $20 Billion from NVIDIA and Others: Report appeared first on Analytics India Magazine.

Simplismart, Yotta Team Up to Deliver Fast and Local AI Infrastructure for India

Simplismart’s inference-first platform underpins Shakti Studio’s serverless inference layer, ensuring low latency for LLMs.

The post Simplismart, Yotta Team Up to Deliver Fast and Local AI Infrastructure for India appeared first on Analytics India Magazine.

ZillOut Secures ₹2.75 Crore Seed Funding to Enhance India’s Nightlife

ZillOut plans to use the new funds to scale its AI capabilities and expand into international markets.

The post ZillOut Secures ₹2.75 Crore Seed Funding to Enhance India’s Nightlife appeared first on Analytics India Magazine.

If SAP Can Support ChatGPT 5 in a Day, is Enterprise AI Finally Fast?

“No other tech company has more access to semantically rich business data.”

The post If SAP Can Support ChatGPT 5 in a Day, is Enterprise AI Finally Fast? appeared first on Analytics India Magazine.


Stoke Space gives us another reason to take it very seriously

With the new investments, Stoke has raised nearly $1 billion.

Man gets drunk, wakes up with a medical mystery that nearly kills him

This one seems ready-made for a television medical drama.

Bank of England warns AI stock bubble rivals 2000 dotcom peak

Central bank says market concentration hasn't been this extreme in 50 years.

ISPs created so many fees that FCC will kill requirement to list them all

ISPs complained about Biden-era rule, said listing every fee was too hard.

Not a game: Cards Against Humanity avoids tariffs by ditching rules, adding explanations

You absolutely, definitely cannot play it.

Salesforce says it won’t pay extortion demand in 1 billion records breach

Scattered LAPSUS$ Hunters gave Salesforce until Friday to pay or else.

Logitech will brick its $100 Pop smart home buttons on October 15

Logitech's interest in the smart home has appeared to wane in recent years.

Google Pixel 10 Pro Fold review: The ultimate Google phone

Google delivers another phone that is slightly better than its predecessor—is that enough?

Synology caves, walks back some drive restrictions on upcoming NAS models

Policy change affects at least 2025 model Plus, Value, and J-series DiskStations.

Vandals deface ads for AI necklaces that listen to all your conversations

Critics attacked subway ads to defend human friends and broadly criticize AI.

Chemistry Nobel prize awarded for building ordered polymers with metal

Three researchers share prize for structured polymers called metal-organic frameworks.

Actually, we are going to tell you the odds of recovering New Glenn’s second launch

To be financially sustainable, New Glenn must be reused often.

It’s Prime Day 2025 part two, and here are more of the best deals we could find

Updated deals on keyboards, laptops, chargers, cameras, and lots of other stuff!

Insurers balk at paying out huge settlements for claims against AI firms

OpenAI, Anthropic consider using investor funds to settle potential lawsuits.

Floating electrons on a sea of helium

Yes, it's another potential qubit. But it's also some very cool physics.


Child malnutrition in Kenya: AI model can forecast rates six months before they become critical

Acute malnutrition weakens a child’s immune system, which can lead to severe illness and an increased risk of death.

Why higher ed’s AI rush could put corporate interests over public service and independence

Higher education’s embrace of AI reveals deeper trends in institutional priorities − and what’s at risk.

What work means to working-class young men in an age of increasing automation

Automation threatens manual jobs. But what does that mean for working-class young men. And how can policy stop them from being left behind?


The AI valuation bubble is now getting silly | Nils Pratley

The broad parallels are genuinely close to the madness of the late-1990s dotcom bubble

It is easy, at the distance of a quarter of a century, to forget the full madness of the late-1990s dotcom bubble. The tech-heavy Nasdaq index in the US rose by 86% in 1999 alone. Companies only had to announce a hopeful “internet strategy” to see their share prices soar. And the key point is that it went on for ages.

Alan Greenspan, the then chair of the Federal Reserve, used the phrase “irrational exuberance” to describe the mood in stock markets as early as December 1996, more than three years before the bubble finally burst. Infamously, Greenspan himself went on to supercharge the latter stages of the mania by cutting interest rates three times, after a currency crisis in Asia in 1998 and the blow-up of a huge hedge fund, Long-Term Capital Management.

Continue reading...

Typewriter reveals unexpected genius | Brief letters

Guaranteed immortality | Living with rejection | Going like hot cakes | Poetry in lotion | The failure of IA

Bob Brody, you may not yet have achieved great heights as a novelist, but your genius as an inventor should guarantee your immortality (‘Stay true to yourself – and fly closer to the sun’: what I’ve learned from 50 years of rejection, 8 October). The illustration published with your article shows you at work on your typewriter, which appears to take in shredded paper and convert it to a sheet of A4 as you type. Genius.
Noel Chidwick
Edinburgh

• I enjoyed Bob Brody’s piece on learning to live with rejection, but I’m not expecting this letter to be published.
Lindsay Camp
Bristol

Continue reading...

IMF chief warns ‘uncertainty is the new normal’ in global economy

Kristalina Georgieva outlines mounting risks to economic stability before fund’s annual meetings next week

The head of the International Monetary Fund has issued a stark warning about the mounting risks facing the global economy, saying: “Buckle up: uncertainty is the new normal.”

As finance ministers and central bankers prepare to meet in Washington for the IMF’s annual meetings next week, its managing director, Kristalina Georgieva said the world economy had shown surprising resilience in the face of Donald Trump’s trade war.

Continue reading...

‘AI is here to stay and change things’: Mad Max director George Miller on why he is taking part in an AI film festival

The director believes AI has made film-making ‘way more egalitarian’ – and is set to lead the judges at Omni AI film festival in Australia

There’s no arguing the use of artificial intelligence in film-making is getting a bad rap. Last week’s unveiling of Hollywood’s first AI “actress”, Tilly Norwood, generated howls of protest from actors’ unions across the UK and US, where the industry is still reeling from last year’s 118-day strike over, among other issues, the threat of AI.

And earlier this week, Australia’s Productivity Commission was pilloried by Liberals and Greens alike for failing to recognise the dire impact AI may have on the country’s creative industries.

Continue reading...

Bank of England warns of growing risk that AI bubble could burst

Possibility of ‘sharp market correction has increased’, says Bank’s financial policy committee

The Bank of England has warned there is a growing risk of a “sudden correction” in global markets as it raised concerns about soaring valuations of leading AI tech companies.

Policymakers said there were also threats of a “sharp repricing of US dollar assets” if the Federal Reserve lost credibility in the eyes of global investors. It comes as Donald Trump’s continues to attack the US central bank and threaten its independence.

Continue reading...


This Listing for a Rental House Is Mangled With AI So Badly That You’ll Cackle Out Loud

"We live in an era of house catfishing."

The post This Listing for a Rental House Is Mangled With AI So Badly That You’ll Cackle Out Loud appeared first on Futurism.

Man Embraces AI at Work, Gets Rewarded by Boss Replacing Him With It

"I considered the LLM as a collaborator."

The post Man Embraces AI at Work, Gets Rewarded by Boss Replacing Him With It appeared first on Futurism.

Sam Altman Says Copyright Holders Are Begging for Their Characters to Be Included in Sora

Rightsholders are apparently worried their characters won't be put in "enough" Sora videos.

The post Sam Altman Says Copyright Holders Are Begging for Their Characters to Be Included in Sora appeared first on Futurism.

Elon Musk Building Huge Secretive Facility

"They think this area is a sacrifice zone and that people here don’t matter."

The post Elon Musk Building Huge Secretive Facility appeared first on Futurism.

Jeff Bezos Says AI Bubble Is Good Because It Will Eliminate the Weak

"This is real, the benefits to society from AI are going to be gigantic."

The post Jeff Bezos Says AI Bubble Is Good Because It Will Eliminate the Weak appeared first on Futurism.

Bank of England Warns of Impending AI Disaster

"The risk of a sharp market correction has increased."

The post Bank of England Warns of Impending AI Disaster appeared first on Futurism.


Fans Call on Taylor Swift to ‘Do Better’ After Accusations of Using AI for Promo Videos

A scavenger hunt campaign to promote Taylor Swift’s new album, The Life of a Showgirl, resulted in a viral #SwiftiesAgainstAI campaign.

This Startup Wants to Spark a US DeepSeek Moment

With the US falling behind on open source models, one startup has a bold idea for democratizing AI: let anyone run reinforcement learning.


Homeland Security Cyber Personnel Reassigned to Jobs in Trump’s Deportation Push

The US Department of Homeland Security has shifted hundreds of national security specialists, including cyber personnel, into jobs that support President Donald Trump’s deportations and said it would dismiss anyone who refuses to go along, according to current and former DHS employees.

Energy Firms Snap Up Weather Services for Trading Edge in Japan

Weather forecasters are finding a lucrative niche in Japan’s power-trading boom, selling hyper-specialized data to firms seeking an edge in one of the world’s most volatile electricity markets.

Starmer Looks to India for Example on UK Plan for Digital ID

Keir Starmer met with a key architect of India’s digital ID program, as the British prime minister sought guidance on implementing a similar system in the UK.

Why Circular AI Deals Among OpenAI, Nvidia, AMD Are Raising Eyebrows

OpenAI and Nvidia. Oracle and OpenAI. Nvidia and Oracle. Today on the Big Take: AI giants are making circular deals — and some analysts are skeptical.

La Guardia Airport Flights Temporarily Halted on Data Outage

Flights in and out of the LaGuardia airport in the New York area were grounded for an hour due to an equipment outage, further adding to disruptions that have snarled the US airspace amid the government shutdown.

Musk’s xAI Expands Fundraise to $20 Billion | Bloomberg Tech 10/8/2025

Bloomberg’s Caroline Hyde and Ed Ludlow discuss the curious financial structure Elon Musk’s AI startup, xAI, is using to expand its ongoing fundraise. Plus, Tesla unveils cheaper versions of its top-selling EV models. And, the UK Minister for AI discusses increased investments between the UK and US on tech innovation. (Source: Bloomberg)

Household-Battery Startup Raises $1 Billion for Expansion

Household-battery startup Base Power Inc. raised $1 billion to expand its energy-storage business and build a manufacturing plant in Texas.

Corus Entertainment Bondholders to Take Control in Debt-for-Equity Swap

Embattled Canadian broadcaster Corus Entertainment Inc. is moving closer to a restructuring that would give bondholders control of the equity, according to people familiar with the matter.

Google Wants Right to Bundle Gemini AI App With Maps, YouTube

Alphabet Inc.’s Google wants to retain the right to bundle its popular mapping and video apps with its Gemini AI service, a lawyer for the company told a federal judge Wednesday, pushing back on a Justice Department proposal that would bar the practice.

Musk Settles Suit by Ex-Twitter CEO Over Denied Severance Pay

Elon Musk and the company formerly known as Twitter have agreed to resolve a $128 million lawsuit filed last year by former Chief Executive Officer Parag Agrawal and three other top officials who said they were denied severance payments.

SoftBank’s Graphcore Plans $1.3 Billion Chip Investment in India

Graphcore, the British chip designer owned by SoftBank Group Corp., is planning to announce a £1 billion ($1.3 billion) investment package in India that includes a new research hub.

Mercuria’s New Metals Unit Reaps $300 Million So Far This Year

Mercuria Energy Group Ltd.’s new metals division is up by around $300 million in trading profits so far this year, as the firm accelerates its return to the sector after years focused on oil and gas.

David AI Raises $50 Million to Bring Audio Data to AI Models

David AI Labs Inc. a startup selling audio data sets to help train artificial intelligence models, has raised $50 million from investors in a new round of funding — signaling a growing market for startups that provide the building blocks for AI development.

Google’s New Foldable, Smartwatch Emphasize AI Rather Than Hardware Changes

After releasing a trio of Pixel 10 smartphones this summer, Alphabet Inc.’s Google is back with the remainder of its 2025 Pixel lineup.

UK to Appoint ‘Digital Markets Champion’ For Tokenization Effort

The UK government will appoint a so-called digital markets champion to spearhead its efforts to digitize wholesale financial markets using blockchain technology.

Disruptive Ransomware Attacks Plague 'Big Game' Targets

Cybercrime groups are big-game hunting, researchers say.

Planet Labs to Launch Satellites Promising Images in an Hour

Planet Labs PBC will launch a constellation of Earth observation satellites promising to deliver higher-resolution, AI-analyzed images within an hour.

Citadel-Bound Marshall Wace Trader Seeks Slice of Crypto Jackpot

Former Marshall Wace trader Scott Arnold is seeking a cut from the hedge fund’s gains tied to an early investment in Circle Internet Group Inc., claiming he initiated the trade that’s now on track to becoming one of the firm’s most profitable wagers.

New Podcast From Twitch Streamers Is Making Over $58,000 a Month on Patreon

The business show Lemonade Stand has an audience that is 91% male and 60% Gen Z

ASML, Applied Materials Fall After US Panel Slams China Sales

Semiconductor companies including Applied Materials Inc. and ASML Holding NV fell after a US House committee said that the industry was boosting China’s semiconductor industry and supporting its military, raising the specter of further export controls.

Cisco Seeks to Challenge Broadcom in Connecting AI Data Centers

Microsoft and Alibaba evaluating Cisco’s latest networking gear, the company says

Tesla Unveils Cheaper Versions of the Model 3 and Model Y EVs

Tesla unveiled cheaper versions of the Model 3 and Model Y vehicles. The standard Model 3 sedan will start at $36,990 and the Model Y SUV will start at $39,990. Those starting prices are about 13% and 11% cheaper, respectively, than premium longer-range versions of each model. Bloomberg's Max Chafkin reports. (Source: Bloomberg)

Greenland Prime Minister Asks EU Help to Secure Digital Links, Block Threats

Greenland’s prime minister called on the European Union to deepen cooperation on connectivity in the Arctic territory to prevent “unauthorized parties” from disrupting its digital infrastructure.

AMD’s Su Joins the Party With OpenAI for Better or Worse

Welcome to Tech In Depth, our daily newsletter about the business of tech from Bloomberg’s journalists around the world. Today, Ian King reports on the pros and cons of AMD’s agreement with OpenAI to develop computing power.

Alibaba’s Qwen Technology Lead Sets Up In-House Robot AI Team

Alibaba Group Holdings Ltd. has established an in-house team for robotics, joining major global firms in a race to build AI-powered physical products.


Google tells employees: If you want health benefits, sign up with a third-party AI tool

Employees must provide access to a third-party AI tool to receive health benefits, sparking concerns about data privacy and consent among Googlers.

A top Goldman executive is leaving following reports that he wrote unauthorized posts critical of Trump

Goldman's co-head of its business in Spain and Portugal, Alvaro del Castano, is set to depart the firm in the "coming months," according to a memo.

The simple lunch a nutrition researcher feeds his kids every day includes carrots, popcorn, and some ultra-processed foods

A nutrition researcher says he feeds his kids the same lunch each day, and it includes some ultra-processed foods.

I never felt as lost as I did right after graduating college. Getting a full-time job changed that.

The author describes how she felt lost and afraid after graduating from university and moving back in with her parents.

Why the number of disconnected youth is growing — and how to fix it

Many Gen Zers without college degrees aren't even looking for work. We asked experts what's behind the trend that's picked up in recent decades.

How to buy gold and other precious metals from Costco online and in-store

Costco sells gold and silver online and in some warehouses, but buying precious metals is a little different from other purchases. Here's how.

Sam Altman says that intellectual property is a lot trickier for video: 'The video feels much more real and lifelike'

OpenAI CEO Sam Altman was asked about Sora users creating viral videos depicting SpongeBob and Pikachu.

A new laser hair-loss treatment aims to be like going to the dentist twice a year

FoLix, the FDA-cleared laser treatment for hair loss, provides a surgery-free option and uses existing follicles on men and women.

My 95-year-old grandmother doesn't want to move to an assisted living facility. We are stuck with an impossible choice.

My 95-year-old grandmother needs care 24/7 but wants to live on her own. My dad and aunt are left with an impossible decision to make.

Every Andrew Garfield movie, ranked according to critics

"After the Hunt" star Andrew Garfield is known for roles in "The Social Network" and "The Amazing Spider-Man." Here's are all his movies, ranked.

Rivian CEO says EVs have 'become political' but they shouldn't be

Rivian CEO RJ Scaringe said that both Republicans and Democrats were interested in the company's EVs.

I quit my corporate job and spent 18 months living on a sailboat. My mindset's completely shifted now that I'm back on land.

After experiencing burnout at work, I made a plan to quit my job and sail full-time with my husband. Our 18 months at sea taught me important lessons.

Every Daniel Day-Lewis movie, ranked

As Daniel Day-Lewis returns to the big screen with "Anemone," here's a look back at his movies and what critics thought of them.

Ukraine says a massive Russian overnight missile and drone barrage was packed with 100,000 foreign-made parts

Zelenskyy said Russia fired 496 strike drones and 53 missiles in one night, and they had 102,785 foreign-made components, including from the US.

Taylor Swift's $53,000 outfit for a New York City outing is the perfect inspiration for fall fashion

Taylor Swift visited New York City while promoting her new album, "The Life of a Showgirl." She wore a designer outfit and luxury jewelry while there.

How Hollywood creatives are actually using AI — and what they're worried about

A new report highlighted how Hollywood is adopting AI for creative tasks. It also looked at the concerns that workers have.

As gold hits $4,000, precious metals are top sellers at Costco — and a cheat code for boosting its e-commerce business

Gold prices are rallying to fresh highs, and helping Costco show strong online sales growth, too.

Bernie Sanders calls for 'robot tax' to protect workers from the impacts of AI

Sanders released a report this week that said AI could eliminate nearly 100 million jobs over the next decade.

This small business made $1 million in a year with marketing and social media

Mav's Top Buns generated over $1 million in sales within a year by leveraging social media and smart marketing.

Ukraine's war surges demand for a 100-year-old heavy machine gun

FN Browning told Business Insider that annual global demand for its machine guns, including the M2, has doubled compared to 2022.


This Startup Wants to Spark a US DeepSeek Moment

With the US falling behind on open source models, one startup has a bold idea for democratizing AI: let anyone run reinforcement learning.


The Crunchbase Tech Layoffs Tracker

At least 95,000 workers at U.S.-based tech companies were laid off in mass job cuts in 2024, per a Crunchbase News tally, and the cuts are continuing into 2025. See who the latest companies are to cut roles.

Europe’s Venture Scene Held Steady In Q3, Buoyed By Early-Stage Funding And Klarna IPO

All told, European startups pulled in $13.1 billion across more than 1,000 deals last quarter, flat quarter over quarter but up 22% year over year, per Crunchbase data.


Databricks' Commitment to European Sovereignty and Growth

The European Union is home to some of the world’s most innovative companies. Databricks...


AI Is Everywhere. Scaling It in Finance Requires Deeper Responsibility

AI has swept through nearly every sector, and now finance is in the midst of its AI moment, with promises to revolutionize critical processes like credit decisioning and risk assessment. Read more…

The post AI Is Everywhere. Scaling It in Finance Requires Deeper Responsibility appeared first on BigDATAwire.


Introducing the Gemini 2.5 Computer Use model

Available in preview via the API, our Computer Use model is a specialized model built on Gemini 2.5 Pro’s capabilities to power agents that can interact with user interfaces.


Dart Object Oriented For Beginner : Expense Manager Case Study Part 9

Lesson 9: Building the Complete Expense Manager App

Duration: 60 minutes

App Feature: 🎉 Putting It All Together

What You'll Build: A full-featured expense tracking system

Prerequisites: Complete Lessons 1-8

By the end of this lesson, you'll be able to:

  • ✅ Combine all OOP concepts into one application
  • ✅ Organize code into multiple files
  • ✅ Create a command-line interface
  • ✅ Handle user input and validation
  • ✅ Implement CRUD operations (Create, Read, Update, Delete)
  • ✅ Save and load data
  • ✅ Structure a real-world Dart application
  • ✅ Prepare code for Flutter integration

Before we start coding, let's plan our application structure:

expense_manager/
├── lib/
│   ├── models/
│   │   ├── expense.dart
│   │   ├── recurring_expense.dart
│   │   ├── one_time_expense.dart
│   │   └── payment_method.dart
│   │
│   ├── managers/
│   │   └── expense_manager.dart
│   │
│   ├── utils/
│   │   ├── input_helper.dart
│   │   └── display_helper.dart
│   │
│   └── app.dart
│
└── bin/
    └── main.dart

Why this structure?

  • models/ - Data classes (Expense, PaymentMethod, etc.)
  • managers/ - Business logic (ExpenseManager)
  • utils/ - Helper functions (input, display)
  • app.dart - Main application logic
  • main.dart - Entry point

expense.dart

class Expense {
  static int _idCounter = 0;

  final int id;
  String description;
  double amount;
  String category;
  DateTime date;
  String? notes;
  bool isPaid;
  String? paymentMethodName;

  Expense({
    required this.description,
    required this.amount,
    required this.category,
    DateTime? date,
    this.notes,
    this.isPaid = false,
    this.paymentMethodName,
  }) : id = ++_idCounter,
       date = date ?? DateTime.now() {
    if (amount < 0) {
      throw Exception('Amount cannot be negative');
    }
    if (description.trim().isEmpty) {
      throw Exception('Description cannot be empty');
    }
  }

  // Getters
  bool isMajorExpense() => amount > 100;

  bool isThisMonth() {
    DateTime now = DateTime.now();
    return date.year == now.year && date.month == now.month;
  }

  bool isToday() {
    DateTime now = DateTime.now();
    return date.year == now.year && 
           date.month == now.month && 
           date.day == now.day;
  }

  int getDaysAgo() {
    return DateTime.now().difference(date).inDays;
  }

  String getFormattedAmount() => '\$${amount.toStringAsFixed(2)}';

  String getFormattedDate() {
    return '${date.month}/${date.day}/${date.year}';
  }

  String getCategoryEmoji() {
    switch (category) {
      case 'Food': return '🍔';
      case 'Transport': return '🚗';
      case 'Bills': return '💡';
      case 'Entertainment': return '🎬';
      case 'Health': return '💊';
      case 'Shopping': return '🛍️';
      default: return '📝';
    }
  }

  String getSummary() {
    String emoji = isMajorExpense() ? '🔴' : '🟢';
    String paid = isPaid ? '✅' : '❌';
    return '$emoji $paid #$id: $description - ${getFormattedAmount()} [$category]';
  }

  void printDetails() {
    print('─────────────────────────────────────');
    print('ID: #$id');
    print('${getCategoryEmoji()} $description');
    print('Amount: ${getFormattedAmount()}');
    print('Category: $category');
    print('Date: ${getFormattedDate()} (${getDaysAgo()} days ago)');
    print('Status: ${isPaid ? "✅ Paid" : "❌ Unpaid"}');
    if (paymentMethodName != null) {
      print('Payment: $paymentMethodName');
    }
    if (notes != null && notes!.isNotEmpty) {
      print('Notes: $notes');
    }
    print('─────────────────────────────────────');
  }

  // Convert to/from Map for saving
  Map<String, dynamic> toMap() {
    return {
      'id': id,
      'description': description,
      'amount': amount,
      'category': category,
      'date': date.toIso8601String(),
      'notes': notes,
      'isPaid': isPaid,
      'paymentMethodName': paymentMethodName,
    };
  }

  static Expense fromMap(Map<String, dynamic> map) {
    return Expense(
      description: map['description'],
      amount: map['amount'],
      category: map['category'],
      date: DateTime.parse(map['date']),
      notes: map['notes'],
      isPaid: map['isPaid'],
      paymentMethodName: map['paymentMethodName'],
    );
  }
}

recurring_expense.dart

import 'expense.dart';

class RecurringExpense extends Expense {
  String frequency;
  DateTime? nextDueDate;

  RecurringExpense({
    required String description,
    required double amount,
    required String category,
    required this.frequency,
    DateTime? date,
    this.nextDueDate,
    String? notes,
    bool isPaid = false,
  }) : super(
    description: description,
    amount: amount,
    category: category,
    date: date,
    notes: notes,
    isPaid: isPaid,
  ) {
    nextDueDate ??= _calculateNextDueDate();
  }

  DateTime _calculateNextDueDate() {
    switch (frequency) {
      case 'daily':
        return date.add(Duration(days: 1));
      case 'weekly':
        return date.add(Duration(days: 7));
      case 'monthly':
        return DateTime(date.year, date.month + 1, date.day);
      case 'yearly':
        return DateTime(date.year + 1, date.month, date.day);
      default:
        return date;
    }
  }

  double yearlyTotal() {
    switch (frequency) {
      case 'daily': return amount * 365;
      case 'weekly': return amount * 52;
      case 'monthly': return amount * 12;
      case 'yearly': return amount;
      default: return amount;
    }
  }

  bool isDueSoon(int daysThreshold) {
    if (nextDueDate == null) return false;
    int daysUntilDue = nextDueDate!.difference(DateTime.now()).inDays;
    return daysUntilDue <= daysThreshold && daysUntilDue >= 0;
  }

  @override
  void printDetails() {
    print('─────────────────────────────────────');
    print('🔄 RECURRING EXPENSE #$id');
    print('${getCategoryEmoji()} $description');
    print('Amount: ${getFormattedAmount()}/$frequency');
    print('Yearly Total: \$${yearlyTotal().toStringAsFixed(2)}');
    print('Category: $category');
    print('Last Payment: ${getFormattedDate()}');
    if (nextDueDate != null) {
      print('Next Due: ${nextDueDate!.month}/${nextDueDate!.day}/${nextDueDate!.year}');
      if (isDueSoon(3)) {
        print('⚠️  Due soon!');
      }
    }
    print('Status: ${isPaid ? "✅ Paid" : "❌ Unpaid"}');
    if (notes != null && notes!.isNotEmpty) {
      print('Notes: $notes');
    }
    print('─────────────────────────────────────');
  }

  @override
  Map<String, dynamic> toMap() {
    var map = super.toMap();
    map['type'] = 'recurring';
    map['frequency'] = frequency;
    map['nextDueDate'] = nextDueDate?.toIso8601String();
    return map;
  }
}

one_time_expense.dart

import 'expense.dart';

class OneTimeExpense extends Expense {
  String occasion;

  OneTimeExpense({
    required String description,
    required double amount,
    required String category,
    required this.occasion,
    DateTime? date,
    String? notes,
    bool isPaid = false,
  }) : super(
    description: description,
    amount: amount,
    category: category,
    date: date,
    notes: notes,
    isPaid: isPaid,
  );

  bool isSpecialOccasion() {
    return occasion == 'birthday' || 
           occasion == 'anniversary' || 
           occasion == 'holiday' ||
           occasion == 'wedding';
  }

  String getOccasionEmoji() {
    switch (occasion) {
      case 'birthday': return '🎂';
      case 'anniversary': return '💝';
      case 'holiday': return '🎄';
      case 'wedding': return '💒';
      case 'emergency': return '🚨';
      case 'vacation': return '✈️';
      default: return '🎯';
    }
  }

  @override
  void printDetails() {
    print('─────────────────────────────────────');
    print('🎯 ONE-TIME EXPENSE #$id');
    print('${getOccasionEmoji()} $occasion: $description');
    print('${getCategoryEmoji()} Category: $category');
    print('Amount: ${getFormattedAmount()}');
    print('Date: ${getFormattedDate()} (${getDaysAgo()} days ago)');
    print('Status: ${isPaid ? "✅ Paid" : "❌ Unpaid"}');
    if (isSpecialOccasion()) {
      print('✨ Special occasion');
    }
    if (notes != null && notes!.isNotEmpty) {
      print('Notes: $notes');
    }
    print('─────────────────────────────────────');
  }

  @override
  Map<String, dynamic> toMap() {
    var map = super.toMap();
    map['type'] = 'onetime';
    map['occasion'] = occasion;
    return map;
  }
}
import 'dart:io';
import 'dart:convert';
import 'expense.dart';
import 'recurring_expense.dart';
import 'one_time_expense.dart';

class ExpenseManager {
  List<Expense> _expenses = [];
  String _dataFile = 'expenses.json';

  // Add expense
  void addExpense(Expense expense) {
    _expenses.add(expense);
    print('✅ Added expense #${expense.id}');
  }

  // Get all expenses
  List<Expense> getAllExpenses() => List.from(_expenses);

  int getCount() => _expenses.length;

  bool isEmpty() => _expenses.isEmpty;

  // Get by ID
  Expense? getExpenseById(int id) {
    try {
      return _expenses.firstWhere((e) => e.id == id);
    } catch (e) {
      return null;
    }
  }

  // Filter methods
  List<Expense> getByCategory(String category) {
    return _expenses.where((e) => e.category == category).toList();
  }

  List<Expense> getThisMonth() {
    return _expenses.where((e) => e.isThisMonth()).toList();
  }

  List<Expense> getUnpaid() {
    return _expenses.where((e) => !e.isPaid).toList();
  }

  List<RecurringExpense> getRecurringExpenses() {
    return _expenses.whereType<RecurringExpense>().toList();
  }

  List<OneTimeExpense> getOneTimeExpenses() {
    return _expenses.whereType<OneTimeExpense>().toList();
  }

  // Statistics
  double getTotalSpending() {
    return _expenses.fold(0.0, (sum, e) => sum + e.amount);
  }

  double getTotalByCategory(String category) {
    return _expenses
        .where((e) => e.category == category)
        .fold(0.0, (sum, e) => sum + e.amount);
  }

  double getTotalUnpaid() {
    return _expenses
        .where((e) => !e.isPaid)
        .fold(0.0, (sum, e) => sum + e.amount);
  }

  double getAverageExpense() {
    if (_expenses.isEmpty) return 0;
    return getTotalSpending() / _expenses.length;
  }

  Expense? getLargestExpense() {
    if (_expenses.isEmpty) return null;
    return _expenses.reduce((a, b) => a.amount > b.amount ? a : b);
  }

  List<String> getAllCategories() {
    return _expenses.map((e) => e.category).toSet().toList();
  }

  Map<String, double> getCategoryBreakdown() {
    Map<String, double> breakdown = {};
    for (var expense in _expenses) {
      breakdown[expense.category] = 
          (breakdown[expense.category] ?? 0) + expense.amount;
    }
    return breakdown;
  }

  // Sort methods
  List<Expense> sortByAmountDesc() {
    List<Expense> sorted = List.from(_expenses);
    sorted.sort((a, b) => b.amount.compareTo(a.amount));
    return sorted;
  }

  List<Expense> sortByDateDesc() {
    List<Expense> sorted = List.from(_expenses);
    sorted.sort((a, b) => b.date.compareTo(a.date));
    return sorted;
  }

  // Update
  bool updateExpense(int id, {
    String? description,
    double? amount,
    String? category,
    String? notes,
    bool? isPaid,
  }) {
    var expense = getExpenseById(id);
    if (expense == null) return false;

    if (description != null) expense.description = description;
    if (amount != null) expense.amount = amount;
    if (category != null) expense.category = category;
    if (notes != null) expense.notes = notes;
    if (isPaid != null) expense.isPaid = isPaid;

    print('✏️  Updated expense #$id');
    return true;
  }

  // Delete
  bool deleteExpense(int id) {
    int initialLength = _expenses.length;
    _expenses.removeWhere((e) => e.id == id);
    bool removed = _expenses.length < initialLength;

    if (removed) {
      print('🗑️  Deleted expense #$id');
    }
    return removed;
  }

  // Mark as paid
  bool markAsPaid(int id, String paymentMethod) {
    var expense = getExpenseById(id);
    if (expense == null) return false;

    expense.isPaid = true;
    expense.paymentMethodName = paymentMethod;
    print('✅ Marked expense #$id as paid');
    return true;
  }

  // Search
  List<Expense> search(String query) {
    String lowerQuery = query.toLowerCase();
    return _expenses.where((e) => 
      e.description.toLowerCase().contains(lowerQuery) ||
      e.category.toLowerCase().contains(lowerQuery) ||
      (e.notes?.toLowerCase().contains(lowerQuery) ?? false)
    ).toList();
  }

  // Reports
  void printSummary() {
    print('\n${"═" * 50}');
    print('💰 EXPENSE SUMMARY'.padRight(50));
    print('${"═" * 50}');
    print('Total expenses: ${getCount()}');
    print('Total spent: \$${getTotalSpending().toStringAsFixed(2)}');
    print('Average: \$${getAverageExpense().toStringAsFixed(2)}');
    print('Unpaid: \$${getTotalUnpaid().toStringAsFixed(2)}');

    var largest = getLargestExpense();
    if (largest != null) {
      print('Largest: ${largest.description} (${largest.getFormattedAmount()})');
    }

    var recurring = getRecurringExpenses();
    if (recurring.isNotEmpty) {
      double yearlyRecurring = recurring.fold(0.0, (sum, e) => sum + e.yearlyTotal());
      print('Yearly recurring: \$${yearlyRecurring.toStringAsFixed(2)}');
    }

    print('${"═" * 50}\n');
  }

  void printCategoryReport() {
    print('\n📊 CATEGORY BREAKDOWN\n');
    var breakdown = getCategoryBreakdown();
    double total = getTotalSpending();

    if (breakdown.isEmpty) {
      print('No expenses to show');
      return;
    }

    breakdown.forEach((category, amount) {
      double percentage = total > 0 ? (amount / total) * 100 : 0;
      int count = _expenses.where((e) => e.category == category).length;

      print('$category:');
      print('  Amount: \$${amount.toStringAsFixed(2)} (${percentage.toStringAsFixed(1)}%)');
      print('  Count: $count expenses');
      print('');
    });
  }

  void printMonthlyReport() {
    print('\n📅 MONTHLY REPORT\n');
    var thisMonth = getThisMonth();

    if (thisMonth.isEmpty) {
      print('No expenses this month');
      return;
    }

    double total = thisMonth.fold(0.0, (sum, e) => sum + e.amount);
    double unpaid = thisMonth.where((e) => !e.isPaid).fold(0.0, (sum, e) => sum + e.amount);

    print('This month: ${thisMonth.length} expenses');
    print('Total spent: \$${total.toStringAsFixed(2)}');
    print('Unpaid: \$${unpaid.toStringAsFixed(2)}');
    print('\nExpenses:');

    for (var expense in thisMonth) {
      print('  ${expense.getSummary()}');
    }
    print('');
  }

  // Save/Load
  Future<void> saveToFile() async {
    try {
      List<Map<String, dynamic>> data = _expenses.map((e) => e.toMap()).toList();
      String json = JsonEncoder.withIndent('  ').convert(data);
      await File(_dataFile).writeAsString(json);
      print('💾 Saved ${_expenses.length} expenses');
    } catch (e) {
      print('❌ Error saving: $e');
    }
  }

  Future<void> loadFromFile() async {
    try {
      if (!await File(_dataFile).exists()) {
        print('No saved data found');
        return;
      }

      String json = await File(_dataFile).readAsString();
      List<dynamic> data = jsonDecode(json);

      _expenses.clear();
      for (var item in data) {
        String type = item['type'] ?? 'regular';

        if (type == 'recurring') {
          _expenses.add(RecurringExpense(
            description: item['description'],
            amount: item['amount'],
            category: item['category'],
            frequency: item['frequency'],
            date: DateTime.parse(item['date']),
            nextDueDate: item['nextDueDate'] != null 
                ? DateTime.parse(item['nextDueDate']) 
                : null,
            notes: item['notes'],
            isPaid: item['isPaid'],
          ));
        } else if (type == 'onetime') {
          _expenses.add(OneTimeExpense(
            description: item['description'],
            amount: item['amount'],
            category: item['category'],
            occasion: item['occasion'],
            date: DateTime.parse(item['date']),
            notes: item['notes'],
            isPaid: item['isPaid'],
          ));
        } else {
          _expenses.add(Expense.fromMap(item));
        }
      }

      print('📂 Loaded ${_expenses.length} expenses');
    } catch (e) {
      print('❌ Error loading: $e');
    }
  }
}

input_helper.dart

import 'dart:io';

class InputHelper {
  static String readString(String prompt) {
    stdout.write('$prompt: ');
    return stdin.readLineSync() ?? '';
  }

  static int readInt(String prompt, {int? min, int? max}) {
    while (true) {
      stdout.write('$prompt: ');
      String? input = stdin.readLineSync();

      if (input == null || input.isEmpty) {
        print('❌ Please enter a number');
        continue;
      }

      int? number = int.tryParse(input);

      if (number == null) {
        print('❌ Invalid number');
        continue;
      }

      if (min != null && number < min) {
        print('❌ Number must be at least $min');
        continue;
      }

      if (max != null && number > max) {
        print('❌ Number must be at most $max');
        continue;
      }

      return number;
    }
  }

  static double readDouble(String prompt, {double? min}) {
    while (true) {
      stdout.write('$prompt: ');
      String? input = stdin.readLineSync();

      if (input == null || input.isEmpty) {
        print('❌ Please enter a number');
        continue;
      }

      double? number = double.tryParse(input);

      if (number == null) {
        print('❌ Invalid number');
        continue;
      }

      if (min != null && number < min) {
        print('❌ Number must be at least $min');
        continue;
      }

      return number;
    }
  }

  static bool readYesNo(String prompt) {
    while (true) {
      stdout.write('$prompt (y/n): ');
      String? input = stdin.readLineSync()?.toLowerCase();

      if (input == 'y' || input == 'yes') return true;
      if (input == 'n' || input == 'no') return false;

      print('❌ Please enter y or n');
    }
  }

  static String readChoice(String prompt, List<String> options) {
    print('$prompt:');
    for (int i = 0; i < options.length; i++) {
      print('  ${i + 1}. ${options[i]}');
    }

    int choice = readInt('Choose (1-${options.length})', 
                         min: 1, max: options.length);
    return options[choice - 1];
  }

  static void pause() {
    print('\nPress Enter to continue...');
    stdin.readLineSync();
  }
}

display_helper.dart

class DisplayHelper {
  static void clearScreen() {
    print('\n' * 50);  // Simple clear for cross-platform
  }

  static void printHeader(String title) {
    print('\n${"═" * 60}');
    print(title.toUpperCase().padRight(60));
    print('${"═" * 60}\n');
  }

  static void printSuccess(String message) {
    print('✅ $message');
  }

  static void printError(String message) {
    print('❌ $message');
  }

  static void printWarning(String message) {
    print('⚠️  $message');
  }

  static void printInfo(String message) {
    print('ℹ️  $message');
  }

  static void printDivider() {
    print('─' * 60);
  }
}

app.dart

import 'dart:io';
import 'expense_manager.dart';
import 'expense.dart';
import 'recurring_expense.dart';
import 'one_time_expense.dart';
import 'input_helper.dart';
import 'display_helper.dart';

class ExpenseApp {
  final ExpenseManager _manager = ExpenseManager();
  bool _running = true;

  Future<void> run() async {
    DisplayHelper.clearScreen();
    print('🚀 Loading...');
    await _manager.loadFromFile();

    while (_running) {
      _showMainMenu();
      int choice = InputHelper.readInt('\nChoose an option', min: 1, max: 11);

      DisplayHelper.clearScreen();

      switch (choice) {
        case 1:
          _addExpense();
          break;
        case 2:
          _viewAllExpenses();
          break;
        case 3:
          _viewByCategory();
          break;
        case 4:
          _searchExpenses();
          break;
        case 5:
          _viewExpenseDetails();
          break;
        case 6:
          _updateExpense();
          break;
        case 7:
          _deleteExpense();
          break;
        case 8:
          _markAsPaid();
          break;
        case 9:
          _viewReports();
          break;
        case 10:
          await _saveAndExit();
          break;
        case 11:
          _running = false;
          print('👋 Goodbye!');
          break;
      }

      if (_running && choice != 10 && choice != 11) {
        InputHelper.pause();
      }
    }
  }

  void _showMainMenu() {
    DisplayHelper.clearScreen();
    DisplayHelper.printHeader('💰 Expense Manager v1.0');

    if (!_manager.isEmpty()) {
      print('Total: ${_manager.getCount()} expenses | ');
      print('Spent: \$${_manager.getTotalSpending().toStringAsFixed(2)} | ');
      print('Unpaid: \$${_manager.getTotalUnpaid().toStringAsFixed(2)}\n');
    }

    print('1.  ➕ Add Expense');
    print('2.  📋 View All Expenses');
    print('3.  📁 View by Category');
    print('4.  🔍 Search Expenses');
    print('5.  🔎 View Expense Details');
    print('6.  ✏️  Update Expense');
    print('7.  🗑️  Delete Expense');
    print('8.  💳 Mark as Paid');
    print('9.  📊 View Reports');
    print('10. 💾 Save & Exit');
    print('11. 🚪 Exit Without Saving');
  }

  void _addExpense() {
    DisplayHelper.printHeader('➕ Add Expense');

    String type = InputHelper.readChoice('Expense type', [
      'Regular',
      'Recurring (subscriptions, bills)',
      'One-time (special occasion)',
    ]);

    print('');
    String description = InputHelper.readString('Description');
    double amount = InputHelper.readDouble('Amount (\$)', min: 0);

    String category = InputHelper.readChoice('Category', [
      'Food',
      'Transport',
      'Bills',
      'Entertainment',
      'Health',
      'Shopping',
      'Other',
    ]);

    String? notes;
    if (InputHelper.readYesNo('Add notes?')) {
      notes = InputHelper.readString('Notes');
    }

    try {
      if (type == 'Regular') {
        _manager.addExpense(Expense(
          description: description,
          amount: amount,
          category: category,
          notes: notes,
        ));
      } else if (type == 'Recurring (subscriptions, bills)') {
        String frequency = InputHelper.readChoice('Frequency', [
          'daily',
          'weekly',
          'monthly',
          'yearly',
        ]);

        _manager.addExpense(RecurringExpense(
          description: description,
          amount: amount,
          category: category,
          frequency: frequency,
          notes: notes,
        ));
      } else {
        String occasion = InputHelper.readChoice('Occasion', [
          'birthday',
          'anniversary',
          'holiday',
          'wedding',
          'emergency',
          'vacation',
          'other',
        ]);

        _manager.addExpense(OneTimeExpense(
          description: description,
          amount: amount,
          category: category,
          occasion: occasion,
          notes: notes,
        ));
      }

      DisplayHelper.printSuccess('Expense added successfully!');
    } catch (e) {
      DisplayHelper.printError('Failed to add expense: $e');
    }
  }

  void _viewAllExpenses() {
    DisplayHelper.printHeader('📋 All Expenses');

    if (_manager.isEmpty()) {
      DisplayHelper.printInfo('No expenses yet');
      return;
    }

    String sortBy = InputHelper.readChoice('Sort by', [
      'Date (newest first)',
      'Amount (highest first)',
      'ID',
    ]);

    List<Expense> expenses;
    if (sortBy == 'Date (newest first)') {
      expenses = _manager.sortByDateDesc();
    } else if (sortBy == 'Amount (highest first)') {
      expenses = _manager.sortByAmountDesc();
    } else {
      expenses = _manager.getAllExpenses();
    }

    print('');
    for (var expense in expenses) {
      print(expense.getSummary());
    }

    print('\nTotal: ${expenses.length} expenses');
  }

  void _viewByCategory() {
    DisplayHelper.printHeader('📁 View by Category');

    var categories = _manager.getAllCategories();
    if (categories.isEmpty) {
      DisplayHelper.printInfo('No expenses yet');
      return;
    }

    String category = InputHelper.readChoice('Category', categories);
    var expenses = _manager.getByCategory(category);

    print('');
    if (expenses.isEmpty) {
      DisplayHelper.printInfo('No expenses in this category');
      return;
    }

    for (var expense in expenses) {
      print(expense.getSummary());
    }

    double total = expenses.fold(0.0, (sum, e) => sum + e.amount);
    print('\n$category Total: \${total.toStringAsFixed(2)}');
  }

  void _searchExpenses() {
    DisplayHelper.printHeader('🔍 Search Expenses');

    String query = InputHelper.readString('Search for');
    var results = _manager.search(query);

    print('');
    if (results.isEmpty) {
      DisplayHelper.printInfo('No results found');
      return;
    }

    print('Found ${results.length} result(s):\n');
    for (var expense in results) {
      print(expense.getSummary());
    }
  }

  void _viewExpenseDetails() {
    DisplayHelper.printHeader('🔎 View Expense Details');

    if (_manager.isEmpty()) {
      DisplayHelper.printInfo('No expenses yet');
      return;
    }

    int id = InputHelper.readInt('Enter expense ID');
    var expense = _manager.getExpenseById(id);

    print('');
    if (expense == null) {
      DisplayHelper.printError('Expense not found');
      return;
    }

    expense.printDetails();
  }

  void _updateExpense() {
    DisplayHelper.printHeader('✏️  Update Expense');

    if (_manager.isEmpty()) {
      DisplayHelper.printInfo('No expenses yet');
      return;
    }

    int id = InputHelper.readInt('Enter expense ID');
    var expense = _manager.getExpenseById(id);

    if (expense == null) {
      DisplayHelper.printError('Expense not found');
      return;
    }

    print('\nCurrent details:');
    expense.printDetails();

    print('\nWhat would you like to update?');
    print('1. Description');
    print('2. Amount');
    print('3. Category');
    print('4. Notes');
    print('5. Cancel');

    int choice = InputHelper.readInt('Choose', min: 1, max: 5);

    if (choice == 5) {
      print('Cancelled');
      return;
    }

    switch (choice) {
      case 1:
        String newDesc = InputHelper.readString('New description');
        _manager.updateExpense(id, description: newDesc);
        break;
      case 2:
        double newAmount = InputHelper.readDouble('New amount', min: 0);
        _manager.updateExpense(id, amount: newAmount);
        break;
      case 3:
        String newCategory = InputHelper.readChoice('New category', [
          'Food', 'Transport', 'Bills', 'Entertainment', 
          'Health', 'Shopping', 'Other'
        ]);
        _manager.updateExpense(id, category: newCategory);
        break;
      case 4:
        String newNotes = InputHelper.readString('New notes');
        _manager.updateExpense(id, notes: newNotes);
        break;
    }
  }

  void _deleteExpense() {
    DisplayHelper.printHeader('🗑️  Delete Expense');

    if (_manager.isEmpty()) {
      DisplayHelper.printInfo('No expenses yet');
      return;
    }

    int id = InputHelper.readInt('Enter expense ID');
    var expense = _manager.getExpenseById(id);

    if (expense == null) {
      DisplayHelper.printError('Expense not found');
      return;
    }

    print('\nExpense to delete:');
    print(expense.getSummary());

    if (InputHelper.readYesNo('\nAre you sure?')) {
      _manager.deleteExpense(id);
    } else {
      print('Cancelled');
    }
  }

  void _markAsPaid() {
    DisplayHelper.printHeader('💳 Mark as Paid');

    var unpaid = _manager.getUnpaid();
    if (unpaid.isEmpty) {
      DisplayHelper.printInfo('No unpaid expenses');
      return;
    }

    print('Unpaid expenses:\n');
    for (var expense in unpaid) {
      print(expense.getSummary());
    }

    print('');
    int id = InputHelper.readInt('Enter expense ID');
    var expense = _manager.getExpenseById(id);

    if (expense == null) {
      DisplayHelper.printError('Expense not found');
      return;
    }

    if (expense.isPaid) {
      DisplayHelper.printWarning('This expense is already paid');
      return;
    }

    String paymentMethod = InputHelper.readChoice('Payment method', [
      'Cash',
      'Credit Card',
      'Debit Card',
      'Digital Wallet',
      'Bank Transfer',
      'Other',
    ]);

    _manager.markAsPaid(id, paymentMethod);
  }

  void _viewReports() {
    DisplayHelper.printHeader('📊 Reports');

    if (_manager.isEmpty()) {
      DisplayHelper.printInfo('No expenses yet');
      return;
    }

    print('1. Summary');
    print('2. Category Breakdown');
    print('3. Monthly Report');
    print('4. All Reports');

    int choice = InputHelper.readInt('Choose', min: 1, max: 4);

    print('');
    switch (choice) {
      case 1:
        _manager.printSummary();
        break;
      case 2:
        _manager.printCategoryReport();
        break;
      case 3:
        _manager.printMonthlyReport();
        break;
      case 4:
        _manager.printSummary();
        _manager.printCategoryReport();
        _manager.printMonthlyReport();
        break;
    }
  }

  Future<void> _saveAndExit() async {
    DisplayHelper.printHeader('💾 Saving');
    await _manager.saveToFile();
    _running = false;
    print('\n✅ Data saved. Goodbye! 👋');
  }
}

main.dart

import 'app.dart';

void main() async {
  var app = ExpenseApp();
  await app.run();
}

How to Run:

  1. Create the project structure:
mkdir expense_manager
cd expense_manager
mkdir lib bin
  1. Create all the files in the appropriate folders

  2. Run the application:

dart run bin/main.dart

Sample Interaction:

═══════════════════════════════════════════════════════════
💰 EXPENSE MANAGER V1.0
═══════════════════════════════════════════════════════════

1.  ➕ Add Expense
2.  📋 View All Expenses
3.  📁 View by Category
4.  🔍 Search Expenses
5.  🔎 View Expense Details
6.  ✏️  Update Expense
7.  🗑️  Delete Expense
8.  💳 Mark as Paid
9.  📊 View Reports
10. 💾 Save & Exit
11. 🚪 Exit Without Saving

Choose an option: 1

═══════════════════════════════════════════════════════════
➕ ADD EXPENSE
═══════════════════════════════════════════════════════════

Expense type:
  1. Regular
  2. Recurring (subscriptions, bills)
  3. One-time (special occasion)
Choose (1-3): 2

Description: Netflix Subscription
Amount ($): 15.99
Category:
  1. Food
  2. Transport
  3. Bills
  4. Entertainment
  5. Health
  6. Shopping
  7. Other
Choose (1-7): 4
Frequency:
  1. daily
  2. weekly
  3. monthly
  4. yearly
Choose (1-4): 3
Add notes? (y/n): y
Notes: Premium 4K plan

✅ Added expense #1

✅ CRUD Operations

  • Create: Add expenses (regular, recurring, one-time)
  • Read: View all, by category, search, view details
  • Update: Modify description, amount, category, notes
  • Delete: Remove expenses with confirmation

✅ Data Persistence

  • Save to JSON file
  • Load from JSON file
  • Auto-save on exit

✅ Different Expense Types

  • Regular expenses
  • Recurring expenses (with frequency and yearly total)
  • One-time expenses (with occasion)

✅ Filtering & Sorting

  • By category
  • By date
  • By amount
  • Search by keyword

✅ Statistics & Reports

  • Total spending
  • Category breakdown
  • Monthly report
  • Unpaid expenses

✅ Payment Tracking

  • Mark as paid
  • Track payment method
  • View unpaid expenses

Ideas for Enhancement:

1. Budget Management

class Budget {
  String category;
  double limit;
  int month;
  int year;

  bool isOverBudget(ExpenseManager manager) {
    double spent = manager.getTotalByCategory(category);
    return spent > limit;
  }
}

2. Export to CSV

void exportToCsv(String filename) {
  var file = File(filename);
  var csv = 'ID,Description,Amount,Category,Date,Paid\n';

  for (var expense in _expenses) {
    csv += '${expense.id},${expense.description},${expense.amount},';
    csv += '${expense.category},${expense.getFormattedDate()},${expense.isPaid}\n';
  }

  file.writeAsStringSync(csv);
  print('📄 Exported to $filename');
}

3. Charts & Visualizations

void printBarChart() {
  var breakdown = getCategoryBreakdown();
  double max = breakdown.values.reduce((a, b) => a > b ? a : b);

  breakdown.forEach((category, amount) {
    int bars = (amount / max * 20).round();
    print('$category: ${"█" * bars} \${amount.toStringAsFixed(2)}');
  });
}

4. Recurring Payment Reminders

void checkUpcomingPayments() {
  var recurring = getRecurringExpenses();

  for (var expense in recurring) {
    if (expense.isDueSoon(3)) {
      print('⚠️  ${expense.description} due in ${expense.nextDueDate!.difference(DateTime.now()).inDays} days');
    }
  }
}

5. Income Tracking

class Income {
  String source;
  double amount;
  DateTime date;

  Income(this.source, this.amount, this.date);
}

class FinanceManager {
  ExpenseManager expenseManager;
  List<Income> incomes = [];

  double getNetBalance() {
    double totalIncome = incomes.fold(0.0, (sum, i) => sum + i.amount);
    double totalExpense = expenseManager.getTotalSpending();
    return totalIncome - totalExpense;
  }
}

Exercise 1: Add Expense Categories Management (Easy)

Allow users to create custom categories instead of using predefined ones.

Hint:

class CategoryManager {
  List<String> _categories = ['Food', 'Transport', 'Bills'];

  void addCategory(String category) { ... }
  void removeCategory(String category) { ... }
  List<String> getAllCategories() { ... }
}

Exercise 2: Implement Budget System (Medium)

Create a budget management system with alerts when spending exceeds limits.

Requirements:

  • Set monthly budget per category
  • Track spending vs budget
  • Show warnings when approaching limit
  • Generate budget report

Exercise 3: Multi-User Support (Hard)

Add user accounts so multiple people can track their expenses separately.

Requirements:

  • User login system
  • Separate expense lists per user
  • User profiles with settings
  • Data saved per user

This command-line app is a perfect foundation for a Flutter app!

Structure Similarities:

Command-line:

ExpenseApp (manages UI flow)
  └── ExpenseManager (manages data)
      └── Expense models

Flutter:

ExpenseApp (MaterialApp)
  └── Screens (HomeScreen, AddScreen, etc.)
      └── ExpenseProvider (state management)
          └── ExpenseManager (same!)
              └── Expense models (same!)

What Stays the Same:

✅ All model classes (Expense, RecurringExpense, etc.)

✅ ExpenseManager class

✅ Business logic

✅ Data persistence

What Changes:

❌ Command-line UI → Flutter widgets

❌ stdin/stdout → TextFields, Buttons

❌ print() → Text widgets

Next Steps for Flutter:

  1. Keep all your model and manager classes
  2. Replace InputHelper with Flutter Forms
  3. Replace DisplayHelper with Flutter widgets
  4. Add state management (Provider, Riverpod, or Bloc)
  5. Create beautiful UI screens

Mistake 1: Not Handling Null Values

// ❌ Wrong - might crash
var expense = _manager.getExpenseById(id);
expense.printDetails();  // Crash if null!

// ✅ Correct - check for null
var expense = _manager.getExpenseById(id);
if (expense == null) {
  print('Expense not found');
  return;
}
expense.printDetails();

Mistake 2: Not Validating User Input

// ❌ Wrong - no validation
double amount = double.parse(input);

// ✅ Correct - validate and handle errors
double? amount = double.tryParse(input);
if (amount == null || amount < 0) {
  print('Invalid amount');
  return;
}

Mistake 3: Forgetting to Save Data

// ❌ Wrong - data lost on exit
void exit() {
  _running = false;
}

// ✅ Correct - save before exit
Future<void> exit() async {
  await _manager.saveToFile();
  _running = false;
}

Mistake 4: Not Using async/await Properly

// ❌ Wrong - doesn't wait for save
void saveData() {
  _manager.saveToFile();
  print('Saved!');  // Prints before save completes!
}

// ✅ Correct - await the operation
Future<void> saveData() async {
  await _manager.saveToFile();
  print('Saved!');  // Prints after save completes
}

Project organization - separate concerns into folders

Model classes - represent data structures

Manager classes - handle business logic

Helper classes - reusable utility functions

CRUD operations - Create, Read, Update, Delete

Data persistence - save/load JSON

User input validation - ensure data quality

Error handling - graceful failure management

Menu-driven UI - clear user flow

1. Why separate models, managers, and helpers into different files?

Answer:

  • Organization: Easy to find and maintain code
  • Reusability: Can use same classes in different projects
  • Testing: Can test each component independently
  • Collaboration: Multiple developers can work on different parts
  • Scalability: Easy to add new features without breaking existing code

2. What's the difference between a model class and a manager class?

Answer:

  • Model: Represents a single entity (one expense) with properties and methods related to that entity
  • Manager: Handles collections and operations on multiple entities (all expenses, filtering, sorting, statistics)

3. Why use async/await for file operations?

Answer:
File operations are slow (I/O bound). Using async/await prevents the app from freezing while waiting for the file operation to complete, allowing other code to run in the meantime.

Congratulations! 🎉

You've completed all 9 lessons and built a complete, working expense manager application using OOP principles!

What You've Learned:

Lesson 1: OOP basics

Lesson 2: Classes and objects

Lesson 3: Constructors

Lesson 4: Encapsulation

Lesson 5: Methods

Lesson 6: Collections management

Lesson 7: Inheritance

Lesson 8: Polymorphism & abstraction

Lesson 9: Complete application

Next Steps:

  1. Enhance the CLI app with the practice exercises
  2. Learn Flutter - convert this to a mobile app
  3. Add database - SQLite for better data storage
  4. Cloud sync - Firebase for multi-device support
  5. Advanced features - charts, budgets, categories
  6. Publish - share your app with others!

Beginner Projects:

  • Todo list manager
  • Contact book
  • Note-taking app
  • Simple calculator with history

Intermediate Projects:

  • Habit tracker
  • Inventory management
  • Recipe organizer
  • Time tracker

Advanced Projects:

  • Budget planner with forecasting
  • Investment portfolio tracker
  • Multi-currency expense manager
  • Business expense reporting system

Official Documentation:

Practice Platforms:

  • DartPad: https://dartpad.dev (online Dart playground)
  • LeetCode: Algorithm practice
  • HackerRank: Coding challenges

Community:

  • Flutter Discord: Join the community
  • r/FlutterDev: Reddit community
  • Stack Overflow: Ask questions

You've accomplished a lot! 🌟

You started knowing nothing about OOP, and now you have:

  • A solid understanding of all core OOP principles
  • Practical experience building a real application
  • Clean, organized, maintainable code
  • A foundation ready for Flutter development

Keep practicing, keep building, and most importantly - have fun coding! 💪

The best way to solidify your knowledge is to build more projects. Take the concepts you've learned and create something new. Every project teaches you something valuable.

Good luck on your coding journey! 🚀

End of Course

Dart Object Oriented For Beginner : Expense Manager Case Study Part 8

Lesson 8: Polymorphism & Abstraction

Duration: 50 minutes

App Feature: 💳 Supporting Multiple Payment Methods

What You'll Build: Abstract classes for payment methods and interfaces

Prerequisites: Complete Lessons 1-7

By the end of this lesson, you'll be able to:

  • ✅ Understand polymorphism in depth
  • ✅ Create abstract classes (templates)
  • ✅ Use abstract methods (contracts)
  • ✅ Implement interfaces with implements
  • ✅ Know when to use abstract classes vs interfaces
  • ✅ Build flexible, extensible code
  • ✅ Work with multiple inheritance through interfaces

Polymorphism means "many forms" - one interface, multiple implementations.

Real-World Example:

Think about a remote control:

🎮 Remote Control (Same Button)
├── Press "Play" on TV → Plays TV show
├── Press "Play" on Music → Plays song
├── Press "Play" on Game → Starts game
└── Same action, different results!

In Code:

void main() {
  // One list, multiple types
  List<Expense> expenses = [
    Expense('Coffee', 4.50, 'Food', DateTime.now()),
    RecurringExpense('Netflix', 15.99, 'Entertainment', 'monthly'),
    OneTimeExpense('Gift', 50.0, 'Gifts', DateTime.now(), 'birthday'),
  ];

  // Same method call, different behavior!
  for (var expense in expenses) {
    expense.printDetails();  // Each type prints differently
    print('');
  }

  // This is polymorphism in action!
}

Key Benefits:

  • Write code once, works with all types
  • Easy to add new types without changing existing code
  • Flexible and maintainable

Let's say we want to add payment methods to our expenses:

class CreditCard {
  void pay(double amount) {
    print('💳 Paid \$${amount} with credit card');
  }
}

class Cash {
  void payNow(double amount) {  // Different method name!
    print('💵 Paid \$${amount} in cash');
  }
}

class DigitalWallet {
  void makePayment(double amount) {  // Another different name!
    print('📱 Paid \$${amount} with digital wallet');
  }
}

The Problem:

  • Every payment method has different method names
  • Can't treat them uniformly
  • Hard to add new payment methods
  • No guarantee they all have payment functionality

The Solution: Abstract classes and interfaces!

An abstract class is a template that defines what methods child classes MUST implement.

// Abstract class - cannot be instantiated directly
abstract class PaymentMethod {
  String get name;  // Abstract getter

  // Abstract method - no implementation
  void processPayment(double amount);

  // Concrete method - has implementation
  void showReceipt(double amount) {
    print('\n📄 RECEIPT');
    print('Payment method: $name');
    print('Amount: \$${amount.toStringAsFixed(2)}');
    print('✅ Payment successful\n');
  }
}

// Concrete class - implements all abstract members
class CreditCard extends PaymentMethod {
  String cardNumber;

  CreditCard(this.cardNumber);

  @override
  String get name => 'Credit Card';

  @override
  void processPayment(double amount) {
    print('💳 Processing credit card payment...');
    print('Card: ****${cardNumber.substring(cardNumber.length - 4)}');
    showReceipt(amount);
  }
}

class Cash extends PaymentMethod {
  @override
  String get name => 'Cash';

  @override
  void processPayment(double amount) {
    print('💵 Processing cash payment of \$${amount.toStringAsFixed(2)}');
    showReceipt(amount);
  }
}

void main() {
  // Can't do this - abstract class!
  // var payment = PaymentMethod();  // ❌ Error!

  // Must use concrete implementations
  var creditCard = CreditCard('4532123456789012');
  var cash = Cash();

  creditCard.processPayment(50.0);
  cash.processPayment(25.0);
}

Output:

💳 Processing credit card payment...
Card: ****9012

📄 RECEIPT
Payment method: Credit Card
Amount: $50.00
✅ Payment successful

💵 Processing cash payment of $25.00

📄 RECEIPT
Payment method: Cash
Amount: $25.00
✅ Payment successful

Key Points:

abstract class PaymentMethod {
  • abstract keyword means can't create instances directly
  • Used as a template/contract
void processPayment(double amount);
  • Abstract method - no body, just signature
  • Child classes MUST implement this
void showReceipt(double amount) {
  // Has implementation
}
  • Concrete method in abstract class
  • Available to all children

Let's integrate payment methods with our Expense class:

abstract class PaymentMethod {
  String get name;
  void processPayment(double amount);

  void showReceipt(double amount) {
    print('📄 Receipt: $name - \$${amount.toStringAsFixed(2)} ✅');
  }
}

class CreditCard extends PaymentMethod {
  String cardNumber;
  String cardHolder;

  CreditCard(this.cardNumber, this.cardHolder);

  @override
  String get name => 'Credit Card';

  @override
  void processPayment(double amount) {
    print('💳 Charging \$${amount.toStringAsFixed(2)} to $cardHolder\'s card');
    print('   Card: ****${cardNumber.substring(cardNumber.length - 4)}');
    showReceipt(amount);
  }
}

class Cash extends PaymentMethod {
  @override
  String get name => 'Cash';

  @override
  void processPayment(double amount) {
    print('💵 Received \$${amount.toStringAsFixed(2)} in cash');
    showReceipt(amount);
  }
}

class DigitalWallet extends PaymentMethod {
  String walletName;
  String email;

  DigitalWallet(this.walletName, this.email);

  @override
  String get name => 'Digital Wallet ($walletName)';

  @override
  void processPayment(double amount) {
    print('📱 Sending payment request to $email');
    print('   Via: $walletName');
    showReceipt(amount);
  }
}

// Updated Expense class
class Expense {
  String description;
  double amount;
  String category;
  DateTime date;
  PaymentMethod? paymentMethod;

  Expense(this.description, this.amount, this.category, this.date);

  void payWith(PaymentMethod method) {
    paymentMethod = method;
    print('\nProcessing payment for: $description (\$${amount.toStringAsFixed(2)})');
    method.processPayment(amount);
  }

  void printDetails() {
    String payment = paymentMethod != null 
        ? 'Paid with: ${paymentMethod!.name}' 
        : 'Not paid yet';
    print('$description: \$${amount.toStringAsFixed(2)} [$category]');
    print('$payment');
  }
}

void main() {
  var rent = Expense('Monthly rent', 1200.0, 'Bills', DateTime.now());
  var coffee = Expense('Coffee', 4.50, 'Food', DateTime.now());
  var laptop = Expense('New laptop', 899.99, 'Electronics', DateTime.now());

  // Pay with different methods
  rent.payWith(CreditCard('4532123456789012', 'John Doe'));
  coffee.payWith(Cash());
  laptop.payWith(DigitalWallet('PayPal', 'john@example.com'));

  print('\n' + '═' * 40);
  print('EXPENSE SUMMARY');
  print('═' * 40);
  rent.printDetails();
  print('');
  coffee.printDetails();
  print('');
  laptop.printDetails();
}

Dart doesn't have a separate interface keyword. Instead, any class can be used as an interface with implements.

Difference:

  • extends = IS-A relationship, inherit implementation
  • implements = HAS-A contract, must implement all methods yourself
// Can use any class as an interface
abstract class Printable {
  void printDocument();
  String getDocumentName();
}

abstract class Saveable {
  void save();
  void load();
}

// Implement multiple interfaces
class Report implements Printable, Saveable {
  String title;
  String content;

  Report(this.title, this.content);

  @override
  void printDocument() {
    print('🖨️ Printing: $title');
    print(content);
  }

  @override
  String getDocumentName() {
    return title;
  }

  @override
  void save() {
    print('💾 Saving report: $title');
  }

  @override
  void load() {
    print('📂 Loading report: $title');
  }
}

void main() {
  var report = Report('Monthly Report', 'Sales increased by 15%');

  report.printDocument();
  report.save();
}

Multiple Inheritance Through Interfaces:

abstract class Taxable {
  double calculateTax(double taxRate);
}

abstract class Discountable {
  double applyDiscount(double discountPercent);
}

// Can implement multiple interfaces
class PurchaseExpense extends Expense implements Taxable, Discountable {
  PurchaseExpense(String desc, double amt, String cat, DateTime date)
    : super(desc, amt, cat, date);

  @override
  double calculateTax(double taxRate) {
    return amount * taxRate;
  }

  @override
  double applyDiscount(double discountPercent) {
    return amount * (1 - discountPercent / 100);
  }

  double getTotalWithTax(double taxRate) {
    return amount + calculateTax(taxRate);
  }
}

void main() {
  var purchase = PurchaseExpense('Laptop', 1000.0, 'Electronics', DateTime.now());

  print('Original: \$${purchase.amount}');
  print('Tax (10%): \$${purchase.calculateTax(0.10).toStringAsFixed(2)}');
  print('Total with tax: \$${purchase.getTotalWithTax(0.10).toStringAsFixed(2)}');
  print('With 15% discount: \$${purchase.applyDiscount(15).toStringAsFixed(2)}');
}

Use Abstract Class When:

✅ You want to share code (concrete methods)

✅ Related classes with common functionality

✅ Define default behavior

✅ IS-A relationship makes sense

Example:

abstract class Expense {
  // Shared properties
  String description;
  double amount;

  // Concrete methods all expenses use
  bool isMajor() => amount > 100;

  // Abstract method children customize
  void printDetails();
}

Use Interface (implements) When:

✅ Unrelated classes need same contract

✅ Multiple inheritance needed

✅ Just defining capabilities, no shared code

✅ HAS-A capability relationship

Example:

abstract class Printable {
  void print();
}

// Completely different classes, same capability
class Document implements Printable { ... }
class Photo implements Printable { ... }
class Receipt implements Printable { ... }

Let's build a complete payment system with abstract classes:

// Abstract payment method
abstract class PaymentMethod {
  String get name;
  String get icon;

  void processPayment(double amount);

  bool validate() {
    return true;  // Default implementation
  }

  void showReceipt(double amount) {
    print('\n${"─" * 35}');
    print('$icon RECEIPT');
    print('${"─" * 35}');
    print('Payment Method: $name');
    print('Amount: \$${amount.toStringAsFixed(2)}');
    print('Status: ✅ Success');
    print('Date: ${DateTime.now().toString().split('.')[0]}');
    print('${"─" * 35}\n');
  }
}

// Concrete implementations
class CreditCard extends PaymentMethod {
  String cardNumber;
  String cardHolder;
  String expiryDate;
  String cvv;

  CreditCard({
    required this.cardNumber,
    required this.cardHolder,
    required this.expiryDate,
    required this.cvv,
  });

  @override
  String get name => 'Credit Card';

  @override
  String get icon => '💳';

  @override
  bool validate() {
    // Simple validation
    if (cardNumber.length != 16) return false;
    if (cvv.length != 3) return false;
    // Check expiry date
    return true;
  }

  @override
  void processPayment(double amount) {
    if (!validate()) {
      print('❌ Invalid card details');
      return;
    }

    print('$icon Processing credit card payment...');
    print('Cardholder: $cardHolder');
    print('Card: ****${cardNumber.substring(12)}');
    print('Expiry: $expiryDate');
    showReceipt(amount);
  }
}

class DebitCard extends PaymentMethod {
  String cardNumber;
  String pin;
  double balance;

  DebitCard({
    required this.cardNumber,
    required this.pin,
    required this.balance,
  });

  @override
  String get name => 'Debit Card';

  @override
  String get icon => '💳';

  @override
  bool validate() {
    return pin.length == 4 && balance > 0;
  }

  @override
  void processPayment(double amount) {
    if (!validate()) {
      print('❌ Invalid PIN or insufficient balance');
      return;
    }

    if (balance < amount) {
      print('❌ Insufficient funds. Balance: \$${balance.toStringAsFixed(2)}');
      return;
    }

    balance -= amount;
    print('$icon Processing debit card payment...');
    print('Card: ****${cardNumber.substring(12)}');
    print('New balance: \$${balance.toStringAsFixed(2)}');
    showReceipt(amount);
  }
}

class Cash extends PaymentMethod {
  @override
  String get name => 'Cash';

  @override
  String get icon => '💵';

  @override
  void processPayment(double amount) {
    print('$icon Cash payment received');
    print('Amount: \$${amount.toStringAsFixed(2)}');
    showReceipt(amount);
  }
}

class DigitalWallet extends PaymentMethod {
  String walletName;
  String email;
  String password;

  DigitalWallet({
    required this.walletName,
    required this.email,
    required this.password,
  });

  @override
  String get name => walletName;

  @override
  String get icon => '📱';

  @override
  bool validate() {
    return email.contains('@') && password.length >= 6;
  }

  @override
  void processPayment(double amount) {
    if (!validate()) {
      print('❌ Invalid credentials');
      return;
    }

    print('$icon Connecting to $walletName...');
    print('Account: $email');
    print('Authorizing payment...');
    showReceipt(amount);
  }
}

class BankTransfer extends PaymentMethod {
  String accountNumber;
  String bankName;
  String routingNumber;

  BankTransfer({
    required this.accountNumber,
    required this.bankName,
    required this.routingNumber,
  });

  @override
  String get name => 'Bank Transfer';

  @override
  String get icon => '🏦';

  @override
  void processPayment(double amount) {
    print('$icon Initiating bank transfer...');
    print('Bank: $bankName');
    print('Account: ****${accountNumber.substring(accountNumber.length - 4)}');
    print('Routing: $routingNumber');
    print('⏳ Transfer pending (1-3 business days)');
    showReceipt(amount);
  }
}

// Enhanced Expense with payment
class Expense {
  String description;
  double amount;
  String category;
  DateTime date;
  PaymentMethod? paymentMethod;
  bool isPaid;

  Expense({
    required this.description,
    required this.amount,
    required this.category,
    DateTime? date,
  }) : date = date ?? DateTime.now(),
       isPaid = false;

  void payWith(PaymentMethod method) {
    print('\n${"═" * 40}');
    print('PROCESSING PAYMENT');
    print('${"═" * 40}');
    print('Expense: $description');
    print('Amount: \$${amount.toStringAsFixed(2)}');
    print('Category: $category');
    print('');

    method.processPayment(amount);
    paymentMethod = method;
    isPaid = true;
  }

  void printDetails() {
    String status = isPaid ? '✅ Paid' : '❌ Unpaid';
    String payment = paymentMethod != null 
        ? '${paymentMethod!.icon} ${paymentMethod!.name}' 
        : 'No payment method';

    print('$description: \$${amount.toStringAsFixed(2)} [$category]');
    print('Status: $status | Payment: $payment');
  }
}

void main() {
  print('💰 EXPENSE PAYMENT SYSTEM\n');

  // Create expenses
  var expenses = [
    Expense(description: 'Monthly rent', amount: 1200.0, category: 'Bills'),
    Expense(description: 'Groceries', amount: 127.50, category: 'Food'),
    Expense(description: 'Coffee', amount: 4.50, category: 'Food'),
    Expense(description: 'Laptop', amount: 899.99, category: 'Electronics'),
  ];

  // Create payment methods
  var creditCard = CreditCard(
    cardNumber: '4532123456789012',
    cardHolder: 'John Doe',
    expiryDate: '12/26',
    cvv: '123',
  );

  var debitCard = DebitCard(
    cardNumber: '5105105105105100',
    pin: '1234',
    balance: 5000.0,
  );

  var paypal = DigitalWallet(
    walletName: 'PayPal',
    email: 'john@example.com',
    password: 'secure123',
  );

  var cash = Cash();

  // Pay for expenses
  expenses[0].payWith(creditCard);
  expenses[1].payWith(debitCard);
  expenses[2].payWith(cash);
  expenses[3].payWith(paypal);

  // Summary
  print('\n${"═" * 40}');
  print('PAYMENT SUMMARY');
  print('${"═" * 40}\n');

  for (var expense in expenses) {
    expense.printDetails();
    print('');
  }
}

Exercise 1: Create Cryptocurrency Payment (Easy)

Create a Cryptocurrency payment method with:

  • Properties: walletAddress, coinType (e.g., "Bitcoin", "Ethereum")
  • Validate wallet address is not empty
  • Override all required methods

Solution:

class Cryptocurrency extends PaymentMethod {
  String walletAddress;
  String coinType;

  Cryptocurrency({
    required this.walletAddress,
    required this.coinType,
  });

  @override
  String get name => '$coinType Wallet';

  @override
  String get icon => '₿';

  @override
  bool validate() {
    return walletAddress.isNotEmpty && walletAddress.length > 20;
  }

  @override
  void processPayment(double amount) {
    if (!validate()) {
      print('❌ Invalid wallet address');
      return;
    }

    print('$icon Processing $coinType payment...');
    print('Wallet: ${walletAddress.substring(0, 6)}...${walletAddress.substring(walletAddress.length - 4)}');
    print('⏳ Waiting for blockchain confirmation...');
    showReceipt(amount);
  }
}

void main() {
  var btc = Cryptocurrency(
    walletAddress: '1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa',
    coinType: 'Bitcoin',
  );

  var expense = Expense(
    description: 'Online purchase',
    amount: 250.0,
    category: 'Shopping',
  );

  expense.payWith(btc);
}

Exercise 2: Refundable Interface (Medium)

Create a Refundable interface and implement it for payment methods that support refunds:

Solution:

abstract class Refundable {
  bool canRefund();
  void processRefund(double amount);
}

class CreditCard extends PaymentMethod implements Refundable {
  String cardNumber;
  String cardHolder;
  List<double> transactions = [];

  CreditCard(this.cardNumber, this.cardHolder);

  @override
  String get name => 'Credit Card';

  @override
  String get icon => '💳';

  @override
  void processPayment(double amount) {
    transactions.add(amount);
    print('$icon Charged \$${amount.toStringAsFixed(2)}');
    showReceipt(amount);
  }

  @override
  bool canRefund() {
    return transactions.isNotEmpty;
  }

  @override
  void processRefund(double amount) {
    if (!canRefund()) {
      print('❌ No transactions to refund');
      return;
    }

    print('🔄 Processing refund of \$${amount.toStringAsFixed(2)}');
    print('   Refund will appear in 3-5 business days');
    transactions.add(-amount);  // Negative for refund
  }
}

// Cash doesn't implement Refundable - can't refund cash!
class Cash extends PaymentMethod {
  @override
  String get name => 'Cash';

  @override
  String get icon => '💵';

  @override
  void processPayment(double amount) {
    print('$icon Cash payment: \$${amount.toStringAsFixed(2)}');
    showReceipt(amount);
  }
}

void main() {
  var card = CreditCard('4532123456789012', 'John Doe');
  var cash = Cash();

  card.processPayment(100.0);

  // Can refund credit card
  if (card is Refundable) {
    card.processRefund(50.0);
  }

  cash.processPayment(50.0);

  // Can't refund cash
  if (cash is Refundable) {
    cash.processRefund(25.0);
  } else {
    print('❌ Cash payments cannot be refunded');
  }
}

Exercise 3: Payment Gateway System (Hard)

Create an abstract PaymentGateway class and implement multiple gateways:

Solution:

abstract class PaymentGateway {
  String get gatewayName;
  double get transactionFee;

  bool authenticate(String apiKey);
  String processTransaction(double amount, PaymentMethod method);
  void logTransaction(String transactionId, double amount);
}

class StripeGateway extends PaymentGateway {
  String apiKey;
  List<Map<String, dynamic>> transactionLog = [];

  StripeGateway(this.apiKey);

  @override
  String get gatewayName => 'Stripe';

  @override
  double get transactionFee => 0.029;  // 2.9%

  @override
  bool authenticate(String key) {
    return key == apiKey && key.startsWith('sk_');
  }

  @override
  String processTransaction(double amount, PaymentMethod method) {
    if (!authenticate(apiKey)) {
      return 'AUTH_FAILED';
    }

    double fee = amount * transactionFee;
    double total = amount + fee;

    String transactionId = 'txn_${DateTime.now().millisecondsSinceEpoch}';

    print('\n🔵 Processing via $gatewayName');
    print('Amount: \$${amount.toStringAsFixed(2)}');
    print('Fee: \$${fee.toStringAsFixed(2)}');
    print('Total: \$${total.toStringAsFixed(2)}');
    print('Transaction ID: $transactionId');

    logTransaction(transactionId, total);
    return transactionId;
  }

  @override
  void logTransaction(String transactionId, double amount) {
    transactionLog.add({
      'id': transactionId,
      'amount': amount,
      'timestamp': DateTime.now(),
      'gateway': gatewayName,
    });
  }

  void printTransactionHistory() {
    print('\n📊 TRANSACTION HISTORY ($gatewayName)');
    for (var transaction in transactionLog) {
      print('${transaction['id']}: \$${transaction['amount'].toStringAsFixed(2)} at ${transaction['timestamp']}');
    }
  }
}

class PayPalGateway extends PaymentGateway {
  String email;
  String password;
  List<Map<String, dynamic>> transactionLog = [];

  PayPalGateway(this.email, this.password);

  @override
  String get gatewayName => 'PayPal';

  @override
  double get transactionFee => 0.034;  // 3.4%

  @override
  bool authenticate(String key) {
    return email.contains('@') && password.length >= 6;
  }

  @override
  String processTransaction(double amount, PaymentMethod method) {
    if (!authenticate(email)) {
      return 'AUTH_FAILED';
    }

    double fee = amount * transactionFee;
    double total = amount + fee;

    String transactionId = 'pp_${DateTime.now().millisecondsSinceEpoch}';

    print('\n🔷 Processing via $gatewayName');
    print('Account: $email');
    print('Amount: \$${amount.toStringAsFixed(2)}');
    print('Fee: \$${fee.toStringAsFixed(2)}');
    print('Total: \$${total.toStringAsFixed(2)}');
    print('Transaction ID: $transactionId');

    logTransaction(transactionId, total);
    return transactionId;
  }

  @override
  void logTransaction(String transactionId, double amount) {
    transactionLog.add({
      'id': transactionId,
      'amount': amount,
      'timestamp': DateTime.now(),
      'gateway': gatewayName,
    });
  }
}

void main() {
  var stripe = StripeGateway('sk_test_123456789');
  var paypal = PayPalGateway('merchant@example.com', 'password123');

  var card = CreditCard(
    cardNumber: '4532123456789012',
    cardHolder: 'John Doe',
    expiryDate: '12/26',
    cvv: '123',
  );

  // Process through different gateways
  stripe.processTransaction(100.0, card);
  stripe.processTransaction(250.0, card);

  paypal.processTransaction(75.0, card);

  // Show history
  if (stripe is StripeGateway) {
    stripe.printTransactionHistory();
  }
}

Mistake 1: Trying to Instantiate Abstract Class

// ❌ Wrong - can't create instance
var payment = PaymentMethod();

// ✅ Correct - use concrete class
var payment = CreditCard('1234567890123456', 'John');

Mistake 2: Not Implementing All Abstract Methods

// ❌ Wrong - missing processPayment implementation
class CreditCard extends PaymentMethod {
  String get name => 'Credit Card';
  // Forgot to implement processPayment!
}

// ✅ Correct - implement all abstract methods
class CreditCard extends PaymentMethod {
  String get name => 'Credit Card';

  @override
  void processPayment(double amount) {
    // Implementation
  }
}

Mistake 3: Using extends When You Mean implements

// ❌ Wrong - don't want to inherit implementation
class Report extends Printable {
  // Would need to inherit Printable's code
}

// ✅ Correct - just need the contract
class Report implements Printable {
  // Implement methods yourself
}

Mistake 4: Forgetting @override

// ❌ Wrong - typo goes unnoticed
class CreditCard extends PaymentMethod {
  void procesPayment(double amount) {  // Typo!
    // ...
  }
}

// ✅ Correct - compiler catches typo
class CreditCard extends PaymentMethod {
  @override
  void processPayment(double amount) {
    // ...
  }
}

Polymorphism - one interface, many implementations

Abstract classes - templates that can't be instantiated

Abstract methods - must be implemented by children

Concrete methods - can exist in abstract classes

implements - fulfill a contract without inheriting

Multiple interfaces - class can implement many

Type checking - use is keyword

Abstract for shared code - use when classes are related

Interfaces for contracts - use when classes are unrelated

1. What's the difference between an abstract class and a regular class?

Answer:

  • Abstract class: Cannot be instantiated directly, can have abstract methods (no implementation), used as template
  • Regular class: Can be instantiated, all methods must have implementation

2. When should you use extends vs implements?

Answer:

  • extends: Use when you want to inherit both interface AND implementation (IS-A relationship)
  • implements: Use when you only need to fulfill a contract (HAS-A capability)
  • Can only extends one class, but can implements multiple interfaces

3. Why use abstract classes instead of regular inheritance?

Answer:
Abstract classes force child classes to implement certain methods, creating a contract. They ensure all children have required functionality while still allowing shared code through concrete methods.

Feature Abstract Class Interface (implements)
Keyword abstract class Any class + implements
Can instantiate? ❌ No ❌ No
Concrete methods? ✅ Yes ❌ No (must implement all)
Abstract methods? ✅ Yes ✅ Yes (implicit)
Multiple inheritance? ❌ No (single) ✅ Yes (multiple)
Properties? ✅ Yes Must implement
When to use? Related classes Unrelated capabilities

Here's how everything fits together in a real expense app:

// 1. ABSTRACT CLASSES FOR RELATED TYPES
abstract class Expense {
  String description;
  double amount;
  String category;
  DateTime date;

  Expense(this.description, this.amount, this.category, this.date);

  void printDetails();  // Abstract
  bool isMajorExpense() => amount > 100;  // Concrete
}

class RecurringExpense extends Expense {
  String frequency;

  RecurringExpense(String desc, double amt, String cat, this.frequency)
    : super(desc, amt, cat, DateTime.now());

  @override
  void printDetails() {
    print('🔄 $description: \${amount.toStringAsFixed(2)} ($frequency)');
  }

  double yearlyTotal() {
    if (frequency == 'monthly') return amount * 12;
    if (frequency == 'weekly') return amount * 52;
    return amount;
  }
}

// 2. ABSTRACT CLASS FOR PAYMENT METHODS
abstract class PaymentMethod {
  String get name;
  void processPayment(double amount);
}

class CreditCard extends PaymentMethod {
  String cardNumber;

  CreditCard(this.cardNumber);

  @override
  String get name => 'Credit Card';

  @override
  void processPayment(double amount) {
    print('💳 Charged \${amount.toStringAsFixed(2)}');
  }
}

// 3. INTERFACES FOR CAPABILITIES
abstract class Refundable {
  bool canRefund();
  void processRefund(double amount);
}

abstract class Taxable {
  double calculateTax(double rate);
}

// 4. COMBINE EVERYTHING
class BusinessExpense extends Expense implements Taxable, Refundable {
  String client;
  PaymentMethod? paymentMethod;

  BusinessExpense(String desc, double amt, String cat, this.client)
    : super(desc, amt, cat, DateTime.now());

  @override
  void printDetails() {
    print('💼 $description for $client: \${amount.toStringAsFixed(2)}');
  }

  @override
  double calculateTax(double rate) {
    return amount * rate;
  }

  @override
  bool canRefund() {
    return paymentMethod != null;
  }

  @override
  void processRefund(double amount) {
    print('🔄 Refunding \${amount.toStringAsFixed(2)}');
  }

  void payWith(PaymentMethod method) {
    paymentMethod = method;
    method.processPayment(amount);
  }
}

void main() {
  var expense = BusinessExpense('Client lunch', 150.0, 'Meals', 'Acme Corp');

  expense.printDetails();

  var card = CreditCard('4532123456789012');
  expense.payWith(card);

  print('Tax (10%): \${expense.calculateTax(0.10).toStringAsFixed(2)}');

  if (expense.canRefund()) {
    expense.processRefund(50.0);
  }
}

Output:

💼 Client lunch for Acme Corp: $150.00
💳 Charged $150.00
Tax (10%): $15.00
🔄 Refunding $50.00

Factory Pattern

abstract class ExpenseFactory {
  Expense createExpense(String type, String desc, double amt, String cat);
}

class DefaultExpenseFactory extends ExpenseFactory {
  @override
  Expense createExpense(String type, String desc, double amt, String cat) {
    switch (type) {
      case 'recurring':
        return RecurringExpense(desc, amt, cat, 'monthly');
      case 'onetime':
        return OneTimeExpense(desc, amt, cat, DateTime.now(), 'other');
      default:
        return Expense(desc, amt, cat, DateTime.now());
    }
  }
}

void main() {
  var factory = DefaultExpenseFactory();

  var expense1 = factory.createExpense('recurring', 'Netflix', 15.99, 'Entertainment');
  var expense2 = factory.createExpense('onetime', 'Gift', 50.0, 'Personal');

  expense1.printDetails();
  expense2.printDetails();
}

Strategy Pattern

abstract class PaymentStrategy {
  void pay(double amount);
}

class CreditCardStrategy extends PaymentStrategy {
  @override
  void pay(double amount) {
    print('💳 Paying \${amount.toStringAsFixed(2)} with credit card');
  }
}

class CashStrategy extends PaymentStrategy {
  @override
  void pay(double amount) {
    print('💵 Paying \${amount.toStringAsFixed(2)} with cash');
  }
}

class Expense {
  String description;
  double amount;
  PaymentStrategy? paymentStrategy;

  Expense(this.description, this.amount);

  void setPaymentStrategy(PaymentStrategy strategy) {
    paymentStrategy = strategy;
  }

  void pay() {
    if (paymentStrategy != null) {
      print('Processing payment for: $description');
      paymentStrategy!.pay(amount);
    }
  }
}

void main() {
  var expense = Expense('Dinner', 75.0);

  expense.setPaymentStrategy(CreditCardStrategy());
  expense.pay();

  expense.setPaymentStrategy(CashStrategy());
  expense.pay();
}

In Lesson 9: Building the Complete Expense Manager App, we'll learn:

  • Putting all OOP concepts together
  • Building a complete command-line expense tracker
  • Organizing code into multiple files
  • Best practices for structuring Dart projects
  • Preparing for Flutter UI integration

Example preview:

📱 EXPENSE MANAGER v1.0

1. Add Expense
2. View All Expenses
3. View by Category
4. Monthly Report
5. Pay Expense
6. Exit

Choose an option: _

See you in Lesson 9! 🚀

Practice Ideas:

  1. Create a Subscription payment method that auto-pays monthly
  2. Implement a RewardsCard that gives cashback
  3. Build a PaymentProcessor that handles multiple gateways
  4. Create Exportable interface for exporting data to CSV/JSON

Advanced Topics to Explore:

  • Mixins (combining behaviors without inheritance)
  • Extension methods
  • Generic types with abstract classes
  • Sealed classes (coming in future Dart versions)

Design Principles:

  • SOLID Principles - Especially Interface Segregation and Dependency Inversion
  • DRY (Don't Repeat Yourself) - Abstract classes help with this
  • Open/Closed - Open for extension, closed for modification

Build a complete payment processing system with:

Requirements:

  1. At least 5 different payment methods (abstract class)
  2. Implement Refundable interface for 3 methods
  3. Implement Recurring interface for subscription payments
  4. Create PaymentGateway abstract class with 2 implementations
  5. Handle payment failures gracefully
  6. Log all transactions
  7. Generate payment reports

Bonus Features:

  • Transaction history
  • Payment analytics (most used method, total fees, etc.)
  • Split payments (pay with multiple methods)
  • Scheduled payments for recurring expenses
  • Receipt generation

This will solidify all the abstract class and polymorphism concepts!

You've now learned:

Polymorphism - treating different types uniformly

Abstract classes - creating templates and contracts

Interfaces - defining capabilities without inheritance

Multiple interfaces - combining multiple capabilities

Design patterns - factory, strategy using abstractions

Real-world architecture - organizing code properly

Key Takeaway: Abstract classes and interfaces are tools for creating flexible, maintainable code. Use abstract classes when classes are related and share code. Use interfaces when defining capabilities across unrelated classes.

Congratulations! You've completed the core OOP lessons. You're now ready to build real applications with proper object-oriented design! 🎉

Next up: Putting it all together in a complete expense manager application!

Dart Object Oriented For Beginner : Expense Manager Case Study Part 7

Lesson 7: Inheritance - Different Types of Expenses

Duration: 45 minutes

App Feature: 🎨 Specialized Expense Types

What You'll Build: Create RecurringExpense and OneTimeExpense classes

Prerequisites: Complete Lessons 1-6

By the end of this lesson, you'll be able to:

  • ✅ Understand what inheritance means
  • ✅ Create child classes that extend parent classes
  • ✅ Use the extends keyword
  • ✅ Call parent constructors with super
  • ✅ Override methods with @override
  • ✅ Add specialized features to child classes
  • ✅ Understand the "IS-A" relationship

Currently, all our expenses are treated identically:

void main() {
  var coffee = Expense.quick('Coffee', 4.50, 'Food');
  var netflix = Expense.quick('Netflix subscription', 15.99, 'Entertainment');
  var birthday = Expense.quick('Birthday gift', 50.0, 'Gifts');

  // But these are fundamentally different!
  // Netflix repeats monthly
  // Birthday gift is one-time
  // Coffee is daily

  // We need a way to distinguish them!
}

The Problem:

  • Some expenses repeat (subscriptions, bills)
  • Some are one-time (gifts, emergency)
  • We want to calculate yearly costs for recurring expenses
  • We want to tag one-time expenses by occasion

The Solution: Create specialized expense types using inheritance!

Inheritance lets you create new classes based on existing ones.

Real-World Analogy:

Think about vehicles:

🚗 Vehicle (Parent)
├── Has wheels
├── Has engine
├── Can drive()

   ├── 🚙 Car (Child)
   │   └── Everything from Vehicle PLUS:
   │       └── Has trunk
   │       └── Seats 4-5 people
   │
   ├── 🚚 Truck (Child)
   │   └── Everything from Vehicle PLUS:
   │       └── Has cargo bed
   │       └── Can tow()
   │
   └── 🏍️ Motorcycle (Child)
       └── Everything from Vehicle PLUS:
           └── Has 2 wheels (overrides parent)
           └── Can wheelie()

Key Points:

  • Car IS-A Vehicle (IS-A relationship)
  • Car inherits all properties and methods from Vehicle
  • Car can add its own properties and methods
  • Car can override inherited methods to change behavior

Let's create RecurringExpense that inherits from Expense:

// Parent class (what we already have)
class Expense {
  String description;
  double amount;
  String category;
  DateTime date;

  Expense(this.description, this.amount, this.category, this.date);

  void printDetails() {
    print('$description: \$${amount.toStringAsFixed(2)} [$category]');
  }

  bool isMajorExpense() => amount > 100;
}

// Child class - extends Expense
class RecurringExpense extends Expense {
  String frequency;  // New property!

  // Constructor
  RecurringExpense(
    String description,
    double amount,
    String category,
    this.frequency,
  ) : super(description, amount, category, DateTime.now());

  // New method specific to RecurringExpense
  double yearlyTotal() {
    if (frequency == 'monthly') return amount * 12;
    if (frequency == 'weekly') return amount * 52;
    if (frequency == 'daily') return amount * 365;
    return amount;  // yearly
  }
}

void main() {
  var netflix = RecurringExpense('Netflix', 15.99, 'Entertainment', 'monthly');

  // Can use methods from parent class
  netflix.printDetails();
  print('Is major? ${netflix.isMajorExpense()}');

  // Can use methods from child class
  print('Yearly cost: \$${netflix.yearlyTotal().toStringAsFixed(2)}');
}

Output:

Netflix: $15.99 [Entertainment]
Is major? false
Yearly cost: $191.88

Let's break down the child class syntax:

class RecurringExpense extends Expense {
  • extends keyword means RecurringExpense inherits from Expense
  • RecurringExpense is the child (or subclass)
  • Expense is the parent (or superclass)
String frequency;  // New property
  • Child classes can add their own properties
  • This property doesn't exist in the parent
RecurringExpense(
  String description,
  double amount,
  String category,
  this.frequency,
) : super(description, amount, category, DateTime.now());
  • super(...) calls the parent constructor
  • Must pass required values to parent
  • Can also initialize child properties
double yearlyTotal() { ... }
  • New method that only exists in RecurringExpense
  • Parent class doesn't have this method

Child classes can override parent methods to change their behavior:

class Expense {
  String description;
  double amount;
  String category;
  DateTime date;

  Expense(this.description, this.amount, this.category, this.date);

  void printDetails() {
    print('$description: \$${amount.toStringAsFixed(2)} [$category]');
  }
}

class RecurringExpense extends Expense {
  String frequency;

  RecurringExpense(
    String description,
    double amount,
    String category,
    this.frequency,
  ) : super(description, amount, category, DateTime.now());

  // Override parent method
  @override
  void printDetails() {
    print('🔄 RECURRING ($frequency)');
    super.printDetails();  // Call parent version
    print('Yearly: \$${yearlyTotal().toStringAsFixed(2)}');
  }

  double yearlyTotal() {
    if (frequency == 'monthly') return amount * 12;
    if (frequency == 'weekly') return amount * 52;
    return amount;
  }
}

void main() {
  var regular = Expense('Coffee', 4.50, 'Food', DateTime.now());
  var netflix = RecurringExpense('Netflix', 15.99, 'Entertainment', 'monthly');

  print('Regular expense:');
  regular.printDetails();

  print('\nRecurring expense:');
  netflix.printDetails();
}

Output:

Regular expense:
Coffee: $4.50 [Food]

Recurring expense:
🔄 RECURRING (monthly)
Netflix: $15.99 [Entertainment]
Yearly: $191.88

Understanding @override:

@override
void printDetails() {
  • @override annotation tells Dart you're intentionally overriding
  • Not required, but highly recommended (helps catch typos)
  • super.printDetails() calls the parent version

Let's create another child class for one-time expenses:

class Expense {
  String description;
  double amount;
  String category;
  DateTime date;

  Expense(this.description, this.amount, this.category, this.date);

  void printDetails() {
    print('$description: \$${amount.toStringAsFixed(2)} [$category]');
  }

  String getSummary() => '$description: \$${amount.toStringAsFixed(2)}';
}

class RecurringExpense extends Expense {
  String frequency;

  RecurringExpense(
    String description,
    double amount,
    String category,
    this.frequency,
  ) : super(description, amount, category, DateTime.now());

  @override
  void printDetails() {
    print('🔄 RECURRING ($frequency)');
    super.printDetails();
    print('   Yearly total: \$${yearlyTotal().toStringAsFixed(2)}');
  }

  double yearlyTotal() {
    if (frequency == 'monthly') return amount * 12;
    if (frequency == 'weekly') return amount * 52;
    if (frequency == 'daily') return amount * 365;
    return amount;
  }
}

class OneTimeExpense extends Expense {
  String occasion;  // 'birthday', 'emergency', 'vacation', etc.

  OneTimeExpense(
    String description,
    double amount,
    String category,
    DateTime date,
    this.occasion,
  ) : super(description, amount, category, date);

  @override
  void printDetails() {
    print('🎯 ONE-TIME ($occasion)');
    super.printDetails();
  }

  bool isSpecialOccasion() {
    return occasion == 'birthday' || 
           occasion == 'anniversary' || 
           occasion == 'holiday';
  }
}

void main() {
  var expenses = [
    Expense('Coffee', 4.50, 'Food', DateTime.now()),
    RecurringExpense('Netflix', 15.99, 'Entertainment', 'monthly'),
    OneTimeExpense('Birthday gift', 75.0, 'Gifts', DateTime.now(), 'birthday'),
    RecurringExpense('Gym', 45.0, 'Health', 'monthly'),
    OneTimeExpense('Car repair', 350.0, 'Transport', DateTime.now(), 'emergency'),
  ];

  print('ALL EXPENSES:\n');
  for (var expense in expenses) {
    expense.printDetails();
    print('');
  }
}

Output:

ALL EXPENSES:

Coffee: $4.50 [Food]

🔄 RECURRING (monthly)
Netflix: $15.99 [Entertainment]
   Yearly total: $191.88

🎯 ONE-TIME (birthday)
Birthday gift: $75.00 [Gifts]

🔄 RECURRING (monthly)
Gym: $45.00 [Health]
   Yearly total: $540.00

🎯 ONE-TIME (emergency)
Car repair: $350.00 [Transport]

Polymorphism means "many forms" - you can treat different types the same way:

void main() {
  // All three types in one list!
  List<Expense> expenses = [
    Expense('Coffee', 4.50, 'Food', DateTime.now()),
    RecurringExpense('Spotify', 9.99, 'Entertainment', 'monthly'),
    OneTimeExpense('Concert', 85.0, 'Entertainment', DateTime.now(), 'fun'),
  ];

  // Same method call, different behavior!
  for (var expense in expenses) {
    expense.printDetails();  // Each type prints differently
    print('');
  }

  // Can check type and use specific features
  for (var expense in expenses) {
    if (expense is RecurringExpense) {
      print('${expense.description} costs \$${expense.yearlyTotal().toStringAsFixed(2)}/year');
    }

    if (expense is OneTimeExpense) {
      print('${expense.description} is for: ${expense.occasion}');
    }
  }
}

Key Points:

  • List<Expense> can hold any type of Expense (parent or children)
  • Each object responds to printDetails() based on its actual type
  • Use is keyword to check the type
  • Can cast to child type to access child-specific features

Let's update our ExpenseManager to work with different expense types:

class ExpenseManager {
  List<Expense> _expenses = [];

  void addExpense(Expense expense) {
    _expenses.add(expense);
  }

  List<Expense> getAllExpenses() => List.from(_expenses);

  // Get only recurring expenses
  List<RecurringExpense> getRecurringExpenses() {
    List<RecurringExpense> recurring = [];
    for (var expense in _expenses) {
      if (expense is RecurringExpense) {
        recurring.add(expense);
      }
    }
    return recurring;
  }

  // Get only one-time expenses
  List<OneTimeExpense> getOneTimeExpenses() {
    List<OneTimeExpense> oneTime = [];
    for (var expense in _expenses) {
      if (expense is OneTimeExpense) {
        oneTime.add(expense);
      }
    }
    return oneTime;
  }

  // Calculate yearly cost of all recurring expenses
  double getYearlyRecurringCost() {
    double total = 0;
    for (var expense in getRecurringExpenses()) {
      total += expense.yearlyTotal();
    }
    return total;
  }

  // Get count of each type
  Map<String, int> getTypeCounts() {
    int regular = 0;
    int recurring = 0;
    int oneTime = 0;

    for (var expense in _expenses) {
      if (expense is RecurringExpense) {
        recurring++;
      } else if (expense is OneTimeExpense) {
        oneTime++;
      } else {
        regular++;
      }
    }

    return {
      'regular': regular,
      'recurring': recurring,
      'oneTime': oneTime,
    };
  }

  void printSummary() {
    print('\n═══════════════════════════════════');
    print('💰 EXPENSE SUMMARY');
    print('═══════════════════════════════════');

    var counts = getTypeCounts();
    print('Total expenses: ${_expenses.length}');
    print('  Regular: ${counts['regular']}');
    print('  Recurring: ${counts['recurring']}');
    print('  One-time: ${counts['oneTime']}');

    double total = 0;
    for (var expense in _expenses) {
      total += expense.amount;
    }
    print('\nTotal spent: \$${total.toStringAsFixed(2)}');

    double yearlyRecurring = getYearlyRecurringCost();
    print('Yearly recurring: \$${yearlyRecurring.toStringAsFixed(2)}');

    print('═══════════════════════════════════\n');
  }

  void printAllExpenses() {
    print('ALL EXPENSES:\n');
    for (var expense in _expenses) {
      expense.printDetails();
      print('');
    }
  }
}

void main() {
  var manager = ExpenseManager();

  // Add different types of expenses
  manager.addExpense(Expense('Coffee', 4.50, 'Food', DateTime.now()));
  manager.addExpense(RecurringExpense('Netflix', 15.99, 'Entertainment', 'monthly'));
  manager.addExpense(OneTimeExpense('Birthday gift', 75.0, 'Gifts', DateTime.now(), 'birthday'));
  manager.addExpense(RecurringExpense('Gym', 45.0, 'Health', 'monthly'));
  manager.addExpense(OneTimeExpense('Car repair', 350.0, 'Transport', DateTime.now(), 'emergency'));
  manager.addExpense(Expense('Lunch', 12.50, 'Food', DateTime.now()));

  manager.printSummary();
  manager.printAllExpenses();

  print('🔄 RECURRING EXPENSES BREAKDOWN:');
  for (var expense in manager.getRecurringExpenses()) {
    print('${expense.description}: \$${expense.amount}/${expense.frequency}');
    print('   → \$${expense.yearlyTotal().toStringAsFixed(2)}/year');
  }
}

Exercise 1: Create BusinessExpense Class (Easy)

Create a BusinessExpense class that extends Expense with:

  • Property: client (String)
  • Property: isReimbursable (bool)
  • Override printDetails() to show client and reimbursable status

Solution:

class BusinessExpense extends Expense {
  String client;
  bool isReimbursable;

  BusinessExpense({
    required String description,
    required double amount,
    required String category,
    required this.client,
    this.isReimbursable = true,
  }) : super(description, amount, category, DateTime.now());

  @override
  void printDetails() {
    print('💼 BUSINESS EXPENSE');
    super.printDetails();
    print('   Client: $client');
    print('   Reimbursable: ${isReimbursable ? "Yes ✅" : "No ❌"}');
  }
}

void main() {
  var expense = BusinessExpense(
    description: 'Client lunch',
    amount: 85.0,
    category: 'Meals',
    client: 'Acme Corp',
    isReimbursable: true,
  );

  expense.printDetails();
}

Exercise 2: Create TravelExpense Class (Medium)

Create a TravelExpense class with:

  • Properties: destination, tripDuration (days)
  • Method: getDailyCost() - returns amount per day
  • Method: isInternational() - returns true if destination is outside country
  • Override printDetails()

Solution:

class TravelExpense extends Expense {
  String destination;
  int tripDuration;

  TravelExpense({
    required String description,
    required double amount,
    required this.destination,
    required this.tripDuration,
    DateTime? date,
  }) : super(description, amount, 'Travel', date ?? DateTime.now());

  double getDailyCost() {
    if (tripDuration == 0) return amount;
    return amount / tripDuration;
  }

  bool isInternational() {
    // Simple check - could be improved with a country list
    return destination.contains('Japan') || 
           destination.contains('USA') || 
           destination.contains('Europe');
  }

  @override
  void printDetails() {
    print('✈️ TRAVEL EXPENSE');
    super.printDetails();
    print('   Destination: $destination');
    print('   Duration: $tripDuration days');
    print('   Daily cost: \$${getDailyCost().toStringAsFixed(2)}');
    print('   International: ${isInternational() ? "Yes 🌍" : "No 🏠"}');
  }
}

void main() {
  var trip = TravelExpense(
    description: 'Tokyo vacation',
    amount: 2500.0,
    destination: 'Tokyo, Japan',
    tripDuration: 7,
  );

  trip.printDetails();
}

Exercise 3: Subscription Management System (Hard)

Create a SubscriptionExpense class that extends RecurringExpense with:

  • Properties: provider, plan, startDate, endDate
  • Method: isActive() - checks if subscription is currently active
  • Method: getRemainingMonths() - months until expiration
  • Method: getTotalCost() - total cost from start to end date
  • Override printDetails()

Solution:

class SubscriptionExpense extends RecurringExpense {
  String provider;
  String plan;
  DateTime startDate;
  DateTime? endDate;

  SubscriptionExpense({
    required String description,
    required double amount,
    required this.provider,
    required this.plan,
    required this.startDate,
    this.endDate,
  }) : super(description, amount, 'Subscriptions', 'monthly');

  bool isActive() {
    DateTime now = DateTime.now();
    if (endDate == null) return true;  // No end date = active
    return now.isBefore(endDate!);
  }

  int getRemainingMonths() {
    if (endDate == null) return -1;  // Unlimited
    DateTime now = DateTime.now();
    if (now.isAfter(endDate!)) return 0;

    int months = (endDate!.year - now.year) * 12 + 
                 (endDate!.month - now.month);
    return months;
  }

  double getTotalCost() {
    if (endDate == null) {
      // If no end date, calculate for 1 year
      return yearlyTotal();
    }

    int months = (endDate!.year - startDate.year) * 12 + 
                 (endDate!.month - startDate.month);
    return amount * months;
  }

  @override
  void printDetails() {
    print('📱 SUBSCRIPTION');
    print('$description ($provider - $plan)');
    print('Amount: \$${amount.toStringAsFixed(2)}/month');
    print('Started: ${startDate.toString().split(' ')[0]}');

    if (endDate != null) {
      print('Expires: ${endDate.toString().split(' ')[0]}');
      print('Remaining: ${getRemainingMonths()} months');
    } else {
      print('Expires: Never (ongoing)');
    }

    print('Status: ${isActive() ? "Active ✅" : "Expired ❌"}');
    print('Total cost: \$${getTotalCost().toStringAsFixed(2)}');
  }
}

void main() {
  var netflix = SubscriptionExpense(
    description: 'Netflix Premium',
    amount: 19.99,
    provider: 'Netflix',
    plan: 'Premium 4K',
    startDate: DateTime(2024, 1, 1),
    endDate: null,  // Ongoing
  );

  var trial = SubscriptionExpense(
    description: 'Adobe Creative Cloud',
    amount: 54.99,
    provider: 'Adobe',
    plan: 'All Apps',
    startDate: DateTime(2025, 9, 1),
    endDate: DateTime(2025, 12, 31),
  );

  netflix.printDetails();
  print('');
  trial.printDetails();
}

Mistake 1: Forgetting to Call super()

// ❌ Wrong - parent constructor not called
class RecurringExpense extends Expense {
  String frequency;

  RecurringExpense(String desc, double amt, String cat, this.frequency);
}

// ✅ Correct - call parent constructor
class RecurringExpense extends Expense {
  String frequency;

  RecurringExpense(String desc, double amt, String cat, this.frequency)
    : super(desc, amt, cat, DateTime.now());
}

Mistake 2: Wrong Parameter Order in super()

// ❌ Wrong - parameters in wrong order
RecurringExpense(String desc, double amt, String cat, this.frequency)
  : super(cat, amt, desc, DateTime.now());  // Wrong order!

// ✅ Correct - match parent constructor signature
RecurringExpense(String desc, double amt, String cat, this.frequency)
  : super(desc, amt, cat, DateTime.now());

Mistake 3: Not Using @override

// ❌ Wrong - typo in method name, no error!
class RecurringExpense extends Expense {
  void printDetail() {  // Missing 's' - creates new method instead of overriding
    print('Details...');
  }
}

// ✅ Correct - @override catches typos
class RecurringExpense extends Expense {
  @override
  void printDetails() {  // Compiler checks this matches parent
    print('Details...');
  }
}

Mistake 4: Trying to Access Private Parent Properties

class Expense {
  String _description;  // Private
  // ...
}

class RecurringExpense extends Expense {
  @override
  void printDetails() {
    print(_description);  // ❌ Error! Can't access private property
  }
}

// ✅ Correct - use getter or make property protected
class Expense {
  String description;  // Public or protected
  // ...
}

class RecurringExpense extends Expense {
  @override
  void printDetails() {
    print(description);  // ✅ Works!
  }
}

Inheritance lets you create specialized classes based on existing ones

extends keyword creates child class from parent

super() calls the parent constructor

@override marks methods that replace parent methods

IS-A relationship - child IS-A type of parent

Polymorphism - treat different types uniformly

Child classes inherit all parent properties and methods

Child classes can add new properties and methods

Use is keyword to check object type

1. What's the difference between inheritance and composition?

Answer:

  • Inheritance (IS-A): RecurringExpense IS-A Expense - creates specialized versions
  • Composition (HAS-A): ExpenseManager HAS-A list of Expenses - contains other objects

2. When should you use inheritance?

Answer:
Use inheritance when:

  • You have a clear IS-A relationship
  • Child needs most/all of parent's features
  • You want to treat different types uniformly (polymorphism)
  • You're specializing behavior, not completely changing it

3. What does @override do?

Answer:
@override tells the compiler you're intentionally replacing a parent method. It helps catch typos - if the method doesn't exist in parent, you'll get an error.

In Lesson 8: Polymorphism Deep Dive, we'll learn:

  • Working with mixed lists of different types
  • Type checking and casting
  • Abstract classes (contracts that child classes must follow)
  • Interfaces with implements
  • When to use inheritance vs interfaces

Example preview:

abstract class Payable {
  void processPayment();
}

class RecurringExpense extends Expense implements Payable {
  @override
  void processPayment() {
    // Auto-pay logic
  }
}

See you in Lesson 8! 🚀

  • Try creating more specialized expense types (GiftExpense, EmergencyExpense, etc.)
  • Think about what makes each type unique
  • Practice using polymorphism with mixed lists
  • Consider when inheritance makes sense vs when it doesn't

Remember: Use inheritance to model IS-A relationships and create specialized versions of existing classes. Don't force it where it doesn't fit naturally! 🌳

Dart Object Oriented For Beginner : Expense Manager Case Study Part 6

Lesson 6: Managing Multiple Expenses

Duration: 40 minutes

App Feature: 📊 Creating an Expense Manager

What You'll Build: A class to manage all your expenses together

Prerequisites: Complete Lessons 1-5

By the end of this lesson, you'll be able to:

  • ✅ Create a manager class to handle collections of objects
  • ✅ Work with Lists of expenses
  • ✅ Add, remove, and update expenses
  • ✅ Filter expenses by various criteria
  • ✅ Calculate totals and statistics
  • ✅ Generate reports from multiple expenses
  • ✅ Sort expenses in different ways

Before we build the ExpenseManager, let's understand Lists:

void main() {
  var manager = ExpenseManager();

  // Add expenses
  manager.addExpense(Expense.quick('Groceries', 127.50, 'Food'));
  manager.addExpense(Expense.quick('Coffee', 4.50, 'Food'));
  manager.addExpense(Expense.quick('Dinner', 45.00, 'Food'));
  manager.addExpense(Expense.quick('Gas', 60.00, 'Transport'));

  // Set budgets
  manager.setBudget('Food', 150.0);
  manager.setBudget('Transport', 100.0);

  // Check budget status
  manager.printBudgetReport();
}

Exercise 3: Advanced Analytics (Hard)

Add these advanced methods:

  • getTopExpenses(int n) - return top N most expensive expenses
  • getCategoryTrend(String category, int days) - return daily average for category over last N days
  • predictMonthlyTotal() - predict month total based on current spending rate

Solution:

class ExpenseManager {
  List<Expense> _expenses = [];

  List<Expense> getTopExpenses(int n) {
    List<Expense> sorted = sortByAmountDesc();
    if (n >= sorted.length) return sorted;
    return sorted.sublist(0, n);
  }

  double getCategoryTrend(String category, int days) {
    DateTime cutoff = DateTime.now().subtract(Duration(days: days));
    var recentExpenses = _expenses.where((e) {
      return e.category == category && e.date.isAfter(cutoff);
    }).toList();

    if (recentExpenses.isEmpty) return 0;

    double total = recentExpenses.fold(0.0, (sum, e) => sum + e.amount);
    return total / days;
  }

  double predictMonthlyTotal() {
    if (_expenses.isEmpty) return 0;

    DateTime now = DateTime.now();
    var thisMonthExpenses = _expenses.where((e) {
      return e.date.year == now.year && e.date.month == now.month;
    }).toList();

    if (thisMonthExpenses.isEmpty) return 0;

    double totalSoFar = thisMonthExpenses.fold(0.0, (sum, e) => sum + e.amount);
    int daysPassed = now.day;
    int daysInMonth = DateTime(now.year, now.month + 1, 0).day;

    double dailyAverage = totalSoFar / daysPassed;
    return dailyAverage * daysInMonth;
  }

  Map<String, double> getCategoryTrends(int days) {
    Map<String, double> trends = {};
    var categories = getAllCategories();

    for (var category in categories) {
      trends[category] = getCategoryTrend(category, days);
    }

    return trends;
  }

  void printTrendReport(int days) {
    print('\n📈 SPENDING TRENDS (Last $days days)\n');
    var trends = getCategoryTrends(days);

    trends.forEach((category, dailyAvg) {
      double monthlyProjection = dailyAvg * 30;
      print('$category:');
      print('  Daily average: \${dailyAvg.toStringAsFixed(2)}');
      print('  Monthly projection: \${monthlyProjection.toStringAsFixed(2)}');
      print('');
    });

    print('💡 Predicted month total: \${predictMonthlyTotal().toStringAsFixed(2)}');
  }
}

void main() {
  var manager = ExpenseManager();

  // Add expenses spread over 15 days
  for (int i = 0; i < 15; i++) {
    var date = DateTime.now().subtract(Duration(days: i));
    manager.addExpense(Expense(
      description: 'Daily expense $i',
      amount: 10.0 + (i * 2),
      category: i % 2 == 0 ? 'Food' : 'Transport',
      date: date,
    ));
  }

  print('🏆 TOP 5 EXPENSES:');
  var top5 = manager.getTopExpenses(5);
  for (int i = 0; i < top5.length; i++) {
    print('${i + 1}. ${top5[i].description} - \${top5[i].amount}');
  }

  manager.printTrendReport(15);
}

Mistake 1: Modifying Original List

// ❌ Wrong - returns reference to internal list
List<Expense> getAllExpenses() {
  return _expenses;  // Can be modified by caller!
}

// ✅ Correct - return a copy
List<Expense> getAllExpenses() {
  return List.from(_expenses);
}

Mistake 2: Not Checking for Empty Lists

// ❌ Wrong - will crash if empty
Expense getLargestExpense() {
  return _expenses[0];  // Error if empty!
}

// ✅ Correct - check first
Expense? getLargestExpense() {
  if (_expenses.isEmpty) return null;
  return _expenses.reduce((a, b) => a.amount > b.amount ? a : b);
}

Mistake 3: Inefficient Filtering

// ❌ Wrong - creates multiple loops
List<Expense> getThisMonthFood() {
  var thisMonth = getThisMonth();
  List<Expense> food = [];
  for (var e in thisMonth) {
    if (e.category == 'Food') food.add(e);
  }
  return food;
}

// ✅ Correct - one pass
List<Expense> getThisMonthFood() {
  return _expenses.where((e) => 
    e.isThisMonth() && e.category == 'Food'
  ).toList();
}

Mistake 4: Not Validating Indices

// ❌ Wrong - no validation
void removeAt(int index) {
  _expenses.removeAt(index);  // Crash if invalid!
}

// ✅ Correct - check bounds
bool removeAt(int index) {
  if (index < 0 || index >= _expenses.length) {
    return false;
  }
  _expenses.removeAt(index);
  return true;
}

Manager classes handle collections of objects

List operations add, remove, filter, sort data

Filter methods return subsets based on criteria

Statistics methods calculate totals, averages, etc.

Sort methods order data in different ways

Report methods display information clearly

Always return copies of internal lists to protect data

Check for empty lists before operations

1. Why should getAllExpenses() return a copy of the list instead of the original?

Answer:
Returning a copy protects the internal list from being modified by external code. If you return the original list, callers can add/remove items directly, bypassing your manager's control and validation.

2. What's the difference between filter methods and sort methods?

Answer:

  • Filter methods: Return a subset of expenses that meet certain criteria (e.g., only Food expenses)
  • Sort methods: Return all expenses but in a different order (e.g., sorted by amount)

3. When should you use where() vs a for loop for filtering?

Answer:
Use where() when possible - it's more concise and functional. Use a for loop when you need more complex logic or need to modify items during iteration.

In Lesson 7: Inheritance - Different Types of Expenses, we'll learn:

  • Creating specialized expense types
  • RecurringExpense class (monthly bills, subscriptions)
  • OneTimeExpense class (special occasions)
  • Using inheritance to reuse code
  • The "IS-A" relationship

Example preview:

class RecurringExpense extends Expense {
  String frequency;  // 'weekly', 'monthly', 'yearly'

  double yearlyTotal() {
    if (frequency == 'monthly') return amount * 12;
    if (frequency == 'weekly') return amount * 52;
    return amount;
  }
}

See you in Lesson 7! 🚀

  • Practice adding more filter methods for different scenarios
  • Try implementing a search feature that searches across all fields
  • Experiment with different sorting combinations
  • Think about what reports would be useful for your expense app

Remember: The ExpenseManager is the brain of your app - it organizes, analyzes, and presents your data. Make it smart and efficient! 💡

Before we build the ExpenseManager, let's understand Lists:

void main() {
  // Creating a list of expenses
  List<Expense> expenses = [];

  // Adding expenses
  expenses.add(Expense.quick('Coffee', 4.50, 'Food'));
  expenses.add(Expense.quick('Lunch', 12.75, 'Food'));
  expenses.add(Expense.quick('Gas', 45.00, 'Transport'));

  // Accessing expenses
  print('First expense: ${expenses[0].description}');
  print('Total count: ${expenses.length}');

  // Looping through expenses
  print('\nAll expenses:');
  for (var expense in expenses) {
    print(expense.getSummary());
  }

  // Removing an expense
  expenses.removeAt(1);  // Remove lunch
  print('\nAfter removing lunch: ${expenses.length} expenses');
}

Key List Operations:

  • add(item) - Add to end
  • insert(index, item) - Add at specific position
  • removeAt(index) - Remove by position
  • remove(item) - Remove by value
  • clear() - Remove all
  • length - Get count
  • [] - Access by index

Let's create our first version:

class ExpenseManager {
  // Private list to store all expenses
  List<Expense> _expenses = [];

  // Add an expense
  void addExpense(Expense expense) {
    _expenses.add(expense);
    print('✅ Added: ${expense.description}');
  }

  // Get all expenses (return a copy to protect internal list)
  List<Expense> getAllExpenses() {
    return List.from(_expenses);
  }

  // Get total number of expenses
  int getCount() {
    return _expenses.length;
  }

  // Calculate total spending
  double getTotalSpending() {
    double total = 0;
    for (var expense in _expenses) {
      total += expense.amount;
    }
    return total;
  }

  // Print a simple summary
  void printSummary() {
    print('\n💰 EXPENSE SUMMARY');
    print('Total expenses: ${getCount()}');
    print('Total spent: \$${getTotalSpending().toStringAsFixed(2)}');
  }
}

void main() {
  var manager = ExpenseManager();

  manager.addExpense(Expense.quick('Coffee', 4.50, 'Food'));
  manager.addExpense(Expense.quick('Uber', 12.00, 'Transport'));
  manager.addExpense(Expense.quick('Lunch', 15.75, 'Food'));

  manager.printSummary();

  print('\nAll expenses:');
  for (var expense in manager.getAllExpenses()) {
    print(expense.getSummary());
  }
}

Output:

✅ Added: Coffee
✅ Added: Uber
✅ Added: Lunch

💰 EXPENSE SUMMARY
Total expenses: 3
Total spent: $32.25

All expenses:
🟢 Coffee: $4.50 [Food]
🟢 Uber: $12.00 [Transport]
🟢 Lunch: $15.75 [Food]

Add methods to filter expenses by different criteria:

class ExpenseManager {
  List<Expense> _expenses = [];

  void addExpense(Expense expense) {
    _expenses.add(expense);
  }

  List<Expense> getAllExpenses() => List.from(_expenses);

  // Filter by category
  List<Expense> getByCategory(String category) {
    List<Expense> filtered = [];
    for (var expense in _expenses) {
      if (expense.category == category) {
        filtered.add(expense);
      }
    }
    return filtered;
  }

  // Filter by amount range
  List<Expense> getByAmountRange(double min, double max) {
    List<Expense> filtered = [];
    for (var expense in _expenses) {
      if (expense.amount >= min && expense.amount <= max) {
        filtered.add(expense);
      }
    }
    return filtered;
  }

  // Get major expenses only
  List<Expense> getMajorExpenses() {
    List<Expense> filtered = [];
    for (var expense in _expenses) {
      if (expense.isMajorExpense()) {
        filtered.add(expense);
      }
    }
    return filtered;
  }

  // Get this month's expenses
  List<Expense> getThisMonth() {
    List<Expense> filtered = [];
    for (var expense in _expenses) {
      if (expense.isThisMonth()) {
        filtered.add(expense);
      }
    }
    return filtered;
  }

  // Get paid/unpaid expenses
  List<Expense> getPaidExpenses() {
    List<Expense> filtered = [];
    for (var expense in _expenses) {
      if (expense.isPaid) {
        filtered.add(expense);
      }
    }
    return filtered;
  }

  List<Expense> getUnpaidExpenses() {
    List<Expense> filtered = [];
    for (var expense in _expenses) {
      if (!expense.isPaid) {
        filtered.add(expense);
      }
    }
    return filtered;
  }
}

void main() {
  var manager = ExpenseManager();

  manager.addExpense(Expense(description: 'Coffee', amount: 4.50, category: 'Food'));
  manager.addExpense(Expense(description: 'Rent', amount: 1200.0, category: 'Bills', isPaid: true));
  manager.addExpense(Expense(description: 'Laptop', amount: 899.99, category: 'Electronics'));
  manager.addExpense(Expense(description: 'Lunch', amount: 15.75, category: 'Food'));

  print('FOOD EXPENSES:');
  for (var expense in manager.getByCategory('Food')) {
    print(expense.getSummary());
  }

  print('\nMAJOR EXPENSES (>$100):');
  for (var expense in manager.getMajorExpenses()) {
    print(expense.getSummary());
  }

  print('\nUNPAID EXPENSES:');
  for (var expense in manager.getUnpaidExpenses()) {
    print(expense.getSummary());
  }
}

Add methods to calculate useful statistics:

class ExpenseManager {
  List<Expense> _expenses = [];

  void addExpense(Expense expense) => _expenses.add(expense);

  // Total spending
  double getTotalSpending() {
    double total = 0;
    for (var expense in _expenses) {
      total += expense.amount;
    }
    return total;
  }

  // Total by category
  double getTotalByCategory(String category) {
    double total = 0;
    for (var expense in _expenses) {
      if (expense.category == category) {
        total += expense.amount;
      }
    }
    return total;
  }

  // Average expense amount
  double getAverageExpense() {
    if (_expenses.isEmpty) return 0;
    return getTotalSpending() / _expenses.length;
  }

  // Largest expense
  Expense? getLargestExpense() {
    if (_expenses.isEmpty) return null;

    Expense largest = _expenses[0];
    for (var expense in _expenses) {
      if (expense.amount > largest.amount) {
        largest = expense;
      }
    }
    return largest;
  }

  // Smallest expense
  Expense? getSmallestExpense() {
    if (_expenses.isEmpty) return null;

    Expense smallest = _expenses[0];
    for (var expense in _expenses) {
      if (expense.amount < smallest.amount) {
        smallest = expense;
      }
    }
    return smallest;
  }

  // Count by category
  int countByCategory(String category) {
    int count = 0;
    for (var expense in _expenses) {
      if (expense.category == category) {
        count++;
      }
    }
    return count;
  }

  // Get all unique categories
  List<String> getAllCategories() {
    List<String> categories = [];
    for (var expense in _expenses) {
      if (!categories.contains(expense.category)) {
        categories.add(expense.category);
      }
    }
    return categories;
  }

  // Total unpaid amount
  double getTotalUnpaid() {
    double total = 0;
    for (var expense in _expenses) {
      if (!expense.isPaid) {
        total += expense.amount;
      }
    }
    return total;
  }

  // Get category breakdown (map of category -> total)
  Map<String, double> getCategoryBreakdown() {
    Map<String, double> breakdown = {};
    for (var expense in _expenses) {
      if (breakdown.containsKey(expense.category)) {
        breakdown[expense.category] = breakdown[expense.category]! + expense.amount;
      } else {
        breakdown[expense.category] = expense.amount;
      }
    }
    return breakdown;
  }
}

void main() {
  var manager = ExpenseManager();

  manager.addExpense(Expense(description: 'Coffee', amount: 4.50, category: 'Food'));
  manager.addExpense(Expense(description: 'Rent', amount: 1200.0, category: 'Bills', isPaid: true));
  manager.addExpense(Expense(description: 'Laptop', amount: 899.99, category: 'Electronics'));
  manager.addExpense(Expense(description: 'Lunch', amount: 15.75, category: 'Food'));
  manager.addExpense(Expense(description: 'Gas', amount: 45.00, category: 'Transport'));

  print('📊 STATISTICS:\n');
  print('Total spending: \$${manager.getTotalSpending().toStringAsFixed(2)}');
  print('Average expense: \$${manager.getAverageExpense().toStringAsFixed(2)}');
  print('Total unpaid: \$${manager.getTotalUnpaid().toStringAsFixed(2)}');

  var largest = manager.getLargestExpense();
  if (largest != null) {
    print('Largest: ${largest.description} - \$${largest.amount}');
  }

  var smallest = manager.getSmallestExpense();
  if (smallest != null) {
    print('Smallest: ${smallest.description} - \$${smallest.amount}');
  }

  print('\n📁 CATEGORY BREAKDOWN:');
  var breakdown = manager.getCategoryBreakdown();
  breakdown.forEach((category, total) {
    print('$category: \$${total.toStringAsFixed(2)}');
  });
}

Add methods to sort expenses in different ways:

class ExpenseManager {
  List<Expense> _expenses = [];

  void addExpense(Expense expense) => _expenses.add(expense);
  List<Expense> getAllExpenses() => List.from(_expenses);

  // Sort by amount (ascending)
  List<Expense> sortByAmountAsc() {
    List<Expense> sorted = List.from(_expenses);
    sorted.sort((a, b) => a.amount.compareTo(b.amount));
    return sorted;
  }

  // Sort by amount (descending)
  List<Expense> sortByAmountDesc() {
    List<Expense> sorted = List.from(_expenses);
    sorted.sort((a, b) => b.amount.compareTo(a.amount));
    return sorted;
  }

  // Sort by date (newest first)
  List<Expense> sortByDateDesc() {
    List<Expense> sorted = List.from(_expenses);
    sorted.sort((a, b) => b.date.compareTo(a.date));
    return sorted;
  }

  // Sort by date (oldest first)
  List<Expense> sortByDateAsc() {
    List<Expense> sorted = List.from(_expenses);
    sorted.sort((a, b) => a.date.compareTo(b.date));
    return sorted;
  }

  // Sort by category
  List<Expense> sortByCategory() {
    List<Expense> sorted = List.from(_expenses);
    sorted.sort((a, b) => a.category.compareTo(b.category));
    return sorted;
  }

  // Sort by description
  List<Expense> sortByDescription() {
    List<Expense> sorted = List.from(_expenses);
    sorted.sort((a, b) => a.description.compareTo(b.description));
    return sorted;
  }
}

void main() {
  var manager = ExpenseManager();

  manager.addExpense(Expense(description: 'Laptop', amount: 899.99, category: 'Electronics', date: DateTime(2025, 10, 5)));
  manager.addExpense(Expense(description: 'Coffee', amount: 4.50, category: 'Food', date: DateTime(2025, 10, 9)));
  manager.addExpense(Expense(description: 'Rent', amount: 1200.0, category: 'Bills', date: DateTime(2025, 10, 1)));
  manager.addExpense(Expense(description: 'Lunch', amount: 15.75, category: 'Food', date: DateTime(2025, 10, 8)));

  print('SORTED BY AMOUNT (highest first):');
  for (var expense in manager.sortByAmountDesc()) {
    print('${expense.description}: \$${expense.amount}');
  }

  print('\nSORTED BY DATE (newest first):');
  for (var expense in manager.sortByDateDesc()) {
    print('${expense.description}: ${expense.getFormattedDate()}');
  }

  print('\nSORTED BY CATEGORY:');
  for (var expense in manager.sortByCategory()) {
    print('${expense.category}: ${expense.description}');
  }
}

Add methods to modify the expense list:

class ExpenseManager {
  List<Expense> _expenses = [];

  void addExpense(Expense expense) {
    _expenses.add(expense);
    print('✅ Added: ${expense.description}');
  }

  // Remove expense by index
  bool removeExpenseAt(int index) {
    if (index < 0 || index >= _expenses.length) {
      print('❌ Invalid index');
      return false;
    }
    var removed = _expenses.removeAt(index);
    print('🗑️ Removed: ${removed.description}');
    return true;
  }

  // Remove expense by description
  bool removeExpenseByDescription(String description) {
    for (int i = 0; i < _expenses.length; i++) {
      if (_expenses[i].description == description) {
        var removed = _expenses.removeAt(i);
        print('🗑️ Removed: ${removed.description}');
        return true;
      }
    }
    print('❌ Expense not found: $description');
    return false;
  }

  // Remove all expenses in a category
  int removeByCategory(String category) {
    int count = 0;
    _expenses.removeWhere((expense) {
      if (expense.category == category) {
        count++;
        return true;
      }
      return false;
    });
    print('🗑️ Removed $count expenses from category: $category');
    return count;
  }

  // Clear all expenses
  void clearAll() {
    int count = _expenses.length;
    _expenses.clear();
    print('🗑️ Cleared all $count expenses');
  }

  // Update expense at index
  bool updateExpense(int index, Expense newExpense) {
    if (index < 0 || index >= _expenses.length) {
      print('❌ Invalid index');
      return false;
    }
    _expenses[index] = newExpense;
    print('✏️ Updated expense at index $index');
    return true;
  }

  // Get expense by index
  Expense? getExpenseAt(int index) {
    if (index < 0 || index >= _expenses.length) {
      return null;
    }
    return _expenses[index];
  }

  // Find index of expense by description
  int findIndexByDescription(String description) {
    for (int i = 0; i < _expenses.length; i++) {
      if (_expenses[i].description == description) {
        return i;
      }
    }
    return -1;
  }
}

void main() {
  var manager = ExpenseManager();

  manager.addExpense(Expense.quick('Coffee', 4.50, 'Food'));
  manager.addExpense(Expense.quick('Lunch', 15.75, 'Food'));
  manager.addExpense(Expense.quick('Gas', 45.00, 'Transport'));

  print('\n--- Removing ---');
  manager.removeExpenseByDescription('Coffee');

  print('\n--- Updating ---');
  int index = manager.findIndexByDescription('Lunch');
  if (index != -1) {
    manager.updateExpense(index, Expense.quick('Dinner', 25.00, 'Food'));
  }

  print('\n--- Final list ---');
  for (var expense in manager.getAllExpenses()) {
    print(expense.getSummary());
  }
}

Here's the full-featured ExpenseManager:

class ExpenseManager {
  List<Expense> _expenses = [];

  // === ADD METHODS ===
  void addExpense(Expense expense) {
    _expenses.add(expense);
  }

  void addMultipleExpenses(List<Expense> expenses) {
    _expenses.addAll(expenses);
    print('✅ Added ${expenses.length} expenses');
  }

  // === GET METHODS ===
  List<Expense> getAllExpenses() => List.from(_expenses);

  int getCount() => _expenses.length;

  bool isEmpty() => _expenses.isEmpty;

  Expense? getExpenseAt(int index) {
    if (index < 0 || index >= _expenses.length) return null;
    return _expenses[index];
  }

  // === FILTER METHODS ===
  List<Expense> getByCategory(String category) {
    return _expenses.where((e) => e.category == category).toList();
  }

  List<Expense> getByAmountRange(double min, double max) {
    return _expenses.where((e) => e.amount >= min && e.amount <= max).toList();
  }

  List<Expense> getMajorExpenses() {
    return _expenses.where((e) => e.isMajorExpense()).toList();
  }

  List<Expense> getThisMonth() {
    return _expenses.where((e) => e.isThisMonth()).toList();
  }

  List<Expense> getPaidExpenses() {
    return _expenses.where((e) => e.isPaid).toList();
  }

  List<Expense> getUnpaidExpenses() {
    return _expenses.where((e) => !e.isPaid).toList();
  }

  // === STATISTICS METHODS ===
  double getTotalSpending() {
    return _expenses.fold(0.0, (sum, e) => sum + e.amount);
  }

  double getTotalByCategory(String category) {
    return _expenses
        .where((e) => e.category == category)
        .fold(0.0, (sum, e) => sum + e.amount);
  }

  double getAverageExpense() {
    if (_expenses.isEmpty) return 0;
    return getTotalSpending() / _expenses.length;
  }

  double getTotalUnpaid() {
    return _expenses
        .where((e) => !e.isPaid)
        .fold(0.0, (sum, e) => sum + e.amount);
  }

  Expense? getLargestExpense() {
    if (_expenses.isEmpty) return null;
    return _expenses.reduce((a, b) => a.amount > b.amount ? a : b);
  }

  Expense? getSmallestExpense() {
    if (_expenses.isEmpty) return null;
    return _expenses.reduce((a, b) => a.amount < b.amount ? a : b);
  }

  int countByCategory(String category) {
    return _expenses.where((e) => e.category == category).length;
  }

  List<String> getAllCategories() {
    return _expenses.map((e) => e.category).toSet().toList();
  }

  Map<String, double> getCategoryBreakdown() {
    Map<String, double> breakdown = {};
    for (var expense in _expenses) {
      breakdown[expense.category] = 
          (breakdown[expense.category] ?? 0) + expense.amount;
    }
    return breakdown;
  }

  Map<String, int> getCategoryCounts() {
    Map<String, int> counts = {};
    for (var expense in _expenses) {
      counts[expense.category] = (counts[expense.category] ?? 0) + 1;
    }
    return counts;
  }

  // === SORT METHODS ===
  List<Expense> sortByAmountDesc() {
    List<Expense> sorted = List.from(_expenses);
    sorted.sort((a, b) => b.amount.compareTo(a.amount));
    return sorted;
  }

  List<Expense> sortByAmountAsc() {
    List<Expense> sorted = List.from(_expenses);
    sorted.sort((a, b) => a.amount.compareTo(b.amount));
    return sorted;
  }

  List<Expense> sortByDateDesc() {
    List<Expense> sorted = List.from(_expenses);
    sorted.sort((a, b) => b.date.compareTo(a.date));
    return sorted;
  }

  List<Expense> sortByCategory() {
    List<Expense> sorted = List.from(_expenses);
    sorted.sort((a, b) => a.category.compareTo(b.category));
    return sorted;
  }

  // === REMOVE METHODS ===
  bool removeExpenseAt(int index) {
    if (index < 0 || index >= _expenses.length) return false;
    _expenses.removeAt(index);
    return true;
  }

  bool removeExpenseByDescription(String description) {
    int initialLength = _expenses.length;
    _expenses.removeWhere((e) => e.description == description);
    return _expenses.length < initialLength;
  }

  int removeByCategory(String category) {
    int initialLength = _expenses.length;
    _expenses.removeWhere((e) => e.category == category);
    return initialLength - _expenses.length;
  }

  void clearAll() {
    _expenses.clear();
  }

  // === SEARCH METHODS ===
  List<Expense> searchByDescription(String query) {
    String lowerQuery = query.toLowerCase();
    return _expenses
        .where((e) => e.description.toLowerCase().contains(lowerQuery))
        .toList();
  }

  int findIndexByDescription(String description) {
    return _expenses.indexWhere((e) => e.description == description);
  }

  // === REPORT METHODS ===
  void printSummary() {
    print('\n═══════════════════════════════════');
    print('💰 EXPENSE SUMMARY');
    print('═══════════════════════════════════');
    print('Total expenses: ${getCount()}');
    print('Total spent: \$${getTotalSpending().toStringAsFixed(2)}');
    print('Average expense: \$${getAverageExpense().toStringAsFixed(2)}');
    print('Total unpaid: \$${getTotalUnpaid().toStringAsFixed(2)}');

    var largest = getLargestExpense();
    if (largest != null) {
      print('Largest: ${largest.description} (\$${largest.amount})');
    }

    print('═══════════════════════════════════\n');
  }

  void printCategoryReport() {
    print('\n📊 CATEGORY BREAKDOWN\n');
    var breakdown = getCategoryBreakdown();
    var counts = getCategoryCounts();
    double total = getTotalSpending();

    breakdown.forEach((category, amount) {
      double percentage = (amount / total) * 100;
      int count = counts[category] ?? 0;
      print('$category:');
      print('  Amount: \$${amount.toStringAsFixed(2)} (${percentage.toStringAsFixed(1)}%)');
      print('  Count: $count expenses');
      print('');
    });
  }

  void printAllExpenses() {
    print('\n📋 ALL EXPENSES\n');
    if (_expenses.isEmpty) {
      print('No expenses to display');
      return;
    }

    for (int i = 0; i < _expenses.length; i++) {
      print('${i + 1}. ${_expenses[i].getFullDisplay()}');
    }
    print('');
  }
}

void main() {
  var manager = ExpenseManager();

  // Add expenses
  manager.addExpense(Expense(description: 'Coffee', amount: 4.50, category: 'Food'));
  manager.addExpense(Expense(description: 'Rent', amount: 1200.0, category: 'Bills', isPaid: true));
  manager.addExpense(Expense(description: 'Laptop', amount: 899.99, category: 'Electronics'));
  manager.addExpense(Expense(description: 'Lunch', amount: 15.75, category: 'Food'));
  manager.addExpense(Expense(description: 'Gas', amount: 45.00, category: 'Transport'));
  manager.addExpense(Expense(description: 'Groceries', amount: 127.50, category: 'Food', isPaid: true));

  // Print reports
  manager.printSummary();
  manager.printCategoryReport();
  manager.printAllExpenses();

  // Filter and display
  print('🍔 FOOD EXPENSES:');
  for (var expense in manager.getByCategory('Food')) {
    print('  ${expense.getSummary()}');
  }

  print('\n🔴 MAJOR EXPENSES:');
  for (var expense in manager.getMajorExpenses()) {
    print('  ${expense.getSummary()}');
  }
}

Exercise 1: Monthly Report (Easy)

Add a method to ExpenseManager:

  • getMonthlyReport(int year, int month) - returns all expenses for that month
  • getMonthlyTotal(int year, int month) - returns total for that month

Solution:

List<Expense> getMonthlyReport(int year, int month) {
  return _expenses.where((e) {
    return e.date.year == year && e.date.month == month;
  }).toList();
}

double getMonthlyTotal(int year, int month) {
  return getMonthlyReport(year, month)
      .fold(0.0, (sum, e) => sum + e.amount);
}

void main() {
  var manager = ExpenseManager();
  // Add expenses...

  var octoberExpenses = manager.getMonthlyReport(2025, 10);
  print('October expenses: ${octoberExpenses.length}');
  print('October total: \$${manager.getMonthlyTotal(2025, 10).toStringAsFixed(2)}');
}

Exercise 2: Budget Tracking (Medium)

Add these methods to ExpenseManager:

  • setBudget(String category, double amount) - set budget for a category
  • isOverBudget(String category) - check if category is over budget
  • getBudgetStatus(String category) - return how much under/over

Solution:


dart
class ExpenseManager {
  List<Expense> _expenses = [];
  Map<String, double> _budgets = {};

  void setBudget(String category, double amount) {
    _budgets[category] = amount;
    print('💰 Set budget for $category: \$${amount.toStringAsFixed(2)}');
  }

  bool isOverBudget(String category) {
    if (!_budgets.containsKey(category)) return false;
    double spent = getTotalByCategory(category);
    return spent > _budgets[category]!;
  }

  String getBudgetStatus(String category) {
    if (!_budgets.containsKey(category)) {
      return 'No budget set for $category';
    }

    double budget = _budgets[category]!;
    double spent = getTotalByCategory(category);
    double remaining = budget - spent;

    if (remaining >= 0) {
      return '\$${remaining.toStringAsFixed(2)} remaining (${((spent/budget)*100).toStringAsFixed(1)}% used)';
    } else {
      return '\$${remaining.abs().toStringAsFixed(2)} over budget!';
    }
  }

  void printBudgetReport() {
    print('\n💰 BUDGET REPORT\n');
    _budgets.forEach((category, budget) {
      double spent = getTotalByCategory(category);
      String status = isOverBudget(category) ? '❌' : '✅';
      print('$status $category:');
      print('   Budget: \$${budget.toStringAsFixed(2)}');
      print('   Spent: \$${spent.toStringAsFixed(2)}');
      print('   ${getBudgetStatus(category)}');
      print('');
    });
  }
}

void main() {

Dart Object Oriented For Beginner : Expense Manager Case Study Part 5

Lesson 5: Adding Useful Features (Methods)

Duration: 30 minutes

App Feature: ✨ Making Expenses Smarter

What You'll Build: Add helpful methods to analyze expenses

Prerequisites: Complete Lessons 1-4

By the end of this lesson, you'll be able to:

  • ✅ Add methods that perform calculations
  • ✅ Create methods that return different types
  • ✅ Use optional and named parameters in methods
  • ✅ Build methods that check conditions
  • ✅ Format data for display
  • ✅ Make your Expense class more powerful

Let's add methods to check various conditions about an expense:

class Expense {
  String _description;
  double _amount;
  String _category;
  DateTime _date;

  Expense(this._description, this._amount, this._category, this._date);

  // Getters
  String get description => _description;
  double get amount => _amount;
  String get category => _category;
  DateTime get date => _date;

  // Boolean methods - return true or false
  bool isMajorExpense() {
    return _amount > 100;
  }

  bool isThisMonth() {
    DateTime now = DateTime.now();
    return _date.year == now.year && _date.month == now.month;
  }

  bool isThisWeek() {
    DateTime now = DateTime.now();
    DateTime startOfWeek = now.subtract(Duration(days: now.weekday - 1));
    DateTime endOfWeek = startOfWeek.add(Duration(days: 6));
    return _date.isAfter(startOfWeek) && _date.isBefore(endOfWeek);
  }

  bool isToday() {
    DateTime now = DateTime.now();
    return _date.year == now.year && 
           _date.month == now.month && 
           _date.day == now.day;
  }

  bool isCategory(String category) {
    return _category == category;
  }

  bool isOlderThan(int days) {
    DateTime now = DateTime.now();
    int difference = now.difference(_date).inDays;
    return difference > days;
  }
}

void main() {
  var coffee = Expense('Coffee', 4.50, 'Food', DateTime.now());
  var laptop = Expense('Laptop', 899.99, 'Electronics', DateTime(2025, 10, 5));

  print('Coffee is major expense? ${coffee.isMajorExpense()}');
  print('Coffee is this month? ${coffee.isThisMonth()}');
  print('Coffee is today? ${coffee.isToday()}');
  print('Coffee is Food? ${coffee.isCategory("Food")}');

  print('\nLaptop is major expense? ${laptop.isMajorExpense()}');
  print('Laptop is older than 3 days? ${laptop.isOlderThan(3)}');
}

Output:

Coffee is major expense? false
Coffee is this month? true
Coffee is today? true
Coffee is Food? true

Laptop is major expense? true
Laptop is older than 3 days? true

Add methods that return nicely formatted data:

class Expense {
  String _description;
  double _amount;
  String _category;
  DateTime _date;

  Expense(this._description, this._amount, this._category, this._date);

  // Getters
  String get description => _description;
  double get amount => _amount;
  String get category => _category;
  DateTime get date => _date;

  // Formatting methods
  String getFormattedAmount() {
    return '\$${_amount.toStringAsFixed(2)}';
  }

  String getFormattedDate() {
    List<String> months = [
      'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
      'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'
    ];
    return '${months[_date.month - 1]} ${_date.day}, ${_date.year}';
  }

  String getShortDate() {
    return '${_date.month}/${_date.day}/${_date.year}';
  }

  String getSummary() {
    String emoji = _amount > 100 ? '🔴' : '🟢';
    return '$emoji $_description: ${getFormattedAmount()} [$_category]';
  }

  String getDetailedSummary() {
    return '''
$_description
Amount: ${getFormattedAmount()}
Category: $_category
Date: ${getFormattedDate()}
''';
  }

  String getCategoryEmoji() {
    switch (_category) {
      case 'Food': return '🍔';
      case 'Transport': return '🚗';
      case 'Bills': return '💡';
      case 'Entertainment': return '🎬';
      case 'Health': return '💊';
      case 'Shopping': return '🛍️';
      default: return '📝';
    }
  }

  String getFullDisplay() {
    return '${getCategoryEmoji()} $_description - ${getFormattedAmount()}';
  }
}

void main() {
  var coffee = Expense('Coffee', 4.50, 'Food', DateTime.now());
  var laptop = Expense('Laptop', 899.99, 'Electronics', DateTime(2025, 10, 5));

  print(coffee.getSummary());
  print(coffee.getFormattedDate());
  print(coffee.getFullDisplay());

  print('\n${laptop.getDetailedSummary()}');
}

Add methods that perform calculations:

class Expense {
  String _description;
  double _amount;
  String _category;
  DateTime _date;

  Expense(this._description, this._amount, this._category, this._date);

  // Getters
  String get description => _description;
  double get amount => _amount;
  String get category => _category;
  DateTime get date => _date;

  // Calculation methods
  int getDaysAgo() {
    DateTime now = DateTime.now();
    return now.difference(_date).inDays;
  }

  double getTax({double taxRate = 0.10}) {
    return _amount * taxRate;
  }

  double getTotalWithTax({double taxRate = 0.10}) {
    return _amount + getTax(taxRate: taxRate);
  }

  double getPercentageOf(double total) {
    if (total == 0) return 0;
    return (_amount / total) * 100;
  }

  double getMonthlyAverage() {
    // Assumes this is an annual expense
    return _amount / 12;
  }

  // Split expense among people
  double splitAmount(int numberOfPeople) {
    if (numberOfPeople <= 0) return _amount;
    return _amount / numberOfPeople;
  }

  // Calculate what this expense would be with a discount
  double applyDiscount(double discountPercent) {
    if (discountPercent < 0 || discountPercent > 100) {
      return _amount;
    }
    return _amount * (1 - discountPercent / 100);
  }
}

void main() {
  var laptop = Expense('Laptop', 1000.0, 'Electronics', DateTime(2025, 10, 5));

  print('Amount: \$${laptop.amount}');
  print('Days ago: ${laptop.getDaysAgo()}');
  print('Tax (10%): \$${laptop.getTax().toStringAsFixed(2)}');
  print('Total with tax: \$${laptop.getTotalWithTax().toStringAsFixed(2)}');
  print('Split 4 ways: \$${laptop.splitAmount(4).toStringAsFixed(2)}');
  print('With 20% discount: \$${laptop.applyDiscount(20).toStringAsFixed(2)}');

  double totalSpending = 5000.0;
  print('Percentage of total: ${laptop.getPercentageOf(totalSpending).toStringAsFixed(1)}%');
}

Output:

Amount: $1000.0
Days ago: 4
Tax (10%): $100.00
Total with tax: $1100.00
Split 4 ways: $250.00
With 20% discount: $800.00
Percentage of total: 20.0%

Create flexible methods using optional parameters:

class Expense {
  String _description;
  double _amount;
  String _category;
  DateTime _date;

  Expense(this._description, this._amount, this._category, this._date);

  // Getters
  String get description => _description;
  double get amount => _amount;
  String get category => _category;
  DateTime get date => _date;

  // Method with optional positional parameter
  void printDetails([bool showEmoji = false]) {
    String emoji = showEmoji ? getCategoryEmoji() : '';
    print('$emoji $_description: \$${_amount.toStringAsFixed(2)} [$_category]');
  }

  // Method with multiple optional parameters
  String format({
    bool showDate = false,
    bool showCategory = true,
    bool showEmoji = false,
    String currency = '\$',
  }) {
    String result = _description;

    if (showEmoji) {
      result = '${getCategoryEmoji()} $result';
    }

    result += ': $currency${_amount.toStringAsFixed(2)}';

    if (showCategory) {
      result += ' [$_category]';
    }

    if (showDate) {
      result += ' (${_date.toString().split(' ')[0]})';
    }

    return result;
  }

  String getCategoryEmoji() {
    switch (_category) {
      case 'Food': return '🍔';
      case 'Transport': return '🚗';
      case 'Bills': return '💡';
      default: return '📝';
    }
  }

  // Method with optional callback
  void process({void Function(String)? onComplete}) {
    // Do some processing
    print('Processing expense: $_description');

    // Call callback if provided
    if (onComplete != null) {
      onComplete('✅ Expense processed successfully');
    }
  }
}

void main() {
  var coffee = Expense('Coffee', 4.50, 'Food', DateTime.now());

  // Different ways to call printDetails
  coffee.printDetails();
  coffee.printDetails(true);

  // Different ways to format
  print('\n${coffee.format()}');
  print(coffee.format(showEmoji: true));
  print(coffee.format(showDate: true, showEmoji: true));
  print(coffee.format(currency: '€', showCategory: false));

  // Using callback
  print('');
  coffee.process(onComplete: (message) {
    print(message);
  });
}

Add methods to compare expenses:

class Expense {
  String _description;
  double _amount;
  String _category;
  DateTime _date;

  Expense(this._description, this._amount, this._category, this._date);

  // Getters
  String get description => _description;
  double get amount => _amount;
  String get category => _category;
  DateTime get date => _date;

  // Comparison methods
  bool isMoreExpensiveThan(Expense other) {
    return _amount > other._amount;
  }

  bool isSameCategory(Expense other) {
    return _category == other._category;
  }

  bool isSameDay(Expense other) {
    return _date.year == other._date.year &&
           _date.month == other._date.month &&
           _date.day == other._date.day;
  }

  bool isNewerThan(Expense other) {
    return _date.isAfter(other._date);
  }

  int compareByAmount(Expense other) {
    if (_amount < other._amount) return -1;
    if (_amount > other._amount) return 1;
    return 0;
  }

  int compareByDate(Expense other) {
    return _date.compareTo(other._date);
  }

  double getDifferenceFrom(Expense other) {
    return (_amount - other._amount).abs();
  }
}

void main() {
  var coffee = Expense('Coffee', 4.50, 'Food', DateTime.now());
  var lunch = Expense('Lunch', 12.75, 'Food', DateTime.now());
  var laptop = Expense('Laptop', 899.99, 'Electronics', DateTime(2025, 10, 5));

  print('Lunch is more expensive than coffee? ${lunch.isMoreExpensiveThan(coffee)}');
  print('Lunch same category as coffee? ${lunch.isSameCategory(coffee)}');
  print('Lunch same day as coffee? ${lunch.isSameDay(coffee)}');
  print('Coffee newer than laptop? ${coffee.isNewerThan(laptop)}');
  print('Difference between lunch and coffee: \$${lunch.getDifferenceFrom(coffee).toStringAsFixed(2)}');
}

Here's a comprehensive Expense class with all useful methods:

class Expense {
  String _description;
  double _amount;
  String _category;
  DateTime _date;
  String? _notes;
  bool _isPaid;

  static const List<String> validCategories = [
    'Food', 'Transport', 'Bills', 'Entertainment', 'Health', 'Shopping', 'Other'
  ];

  Expense({
    required String description,
    required double amount,
    required String category,
    DateTime? date,
    String? notes,
    bool isPaid = false,
  }) : _description = description,
       _amount = amount,
       _category = category,
       _date = date ?? DateTime.now(),
       _notes = notes,
       _isPaid = isPaid {
    if (_amount < 0) throw Exception('Amount cannot be negative');
    if (_description.trim().isEmpty) throw Exception('Description cannot be empty');
    if (!validCategories.contains(_category)) {
      _category = 'Other';
    }
  }

  // Getters
  String get description => _description;
  double get amount => _amount;
  String get category => _category;
  DateTime get date => _date;
  String? get notes => _notes;
  bool get isPaid => _isPaid;

  // Setters
  set amount(double value) {
    if (value < 0) throw Exception('Amount cannot be negative');
    _amount = value;
  }

  set isPaid(bool value) => _isPaid = value;
  set notes(String? value) => _notes = value;

  // Boolean check methods
  bool isMajorExpense() => _amount > 100;
  bool isThisMonth() {
    DateTime now = DateTime.now();
    return _date.year == now.year && _date.month == now.month;
  }
  bool isToday() {
    DateTime now = DateTime.now();
    return _date.year == now.year && _date.month == now.month && _date.day == now.day;
  }
  bool isCategory(String cat) => _category == cat;
  bool isOlderThan(int days) => DateTime.now().difference(_date).inDays > days;

  // Formatting methods
  String getFormattedAmount() => '\$${_amount.toStringAsFixed(2)}';

  String getFormattedDate() {
    List<String> months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
                           'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
    return '${months[_date.month - 1]} ${_date.day}, ${_date.year}';
  }

  String getCategoryEmoji() {
    switch (_category) {
      case 'Food': return '🍔';
      case 'Transport': return '🚗';
      case 'Bills': return '💡';
      case 'Entertainment': return '🎬';
      case 'Health': return '💊';
      case 'Shopping': return '🛍️';
      default: return '📝';
    }
  }

  String getSummary() {
    String emoji = isMajorExpense() ? '🔴' : '🟢';
    return '$emoji $_description: ${getFormattedAmount()} [$_category]';
  }

  String getFullDisplay() {
    String paid = _isPaid ? '✅' : '❌';
    String noteText = _notes != null ? ' - $_notes' : '';
    return '$paid ${getCategoryEmoji()} $_description: ${getFormattedAmount()}$noteText';
  }

  // Calculation methods
  int getDaysAgo() => DateTime.now().difference(_date).inDays;

  double getTax({double taxRate = 0.10}) => _amount * taxRate;

  double getTotalWithTax({double taxRate = 0.10}) => _amount + getTax(taxRate: taxRate);

  double getPercentageOf(double total) {
    if (total == 0) return 0;
    return (_amount / total) * 100;
  }

  double splitAmount(int numberOfPeople) {
    if (numberOfPeople <= 0) return _amount;
    return _amount / numberOfPeople;
  }

  // Comparison methods
  bool isMoreExpensiveThan(Expense other) => _amount > other._amount;
  bool isSameCategory(Expense other) => _category == other._category;
  bool isNewerThan(Expense other) => _date.isAfter(other._date);

  int compareByAmount(Expense other) {
    if (_amount < other._amount) return -1;
    if (_amount > other._amount) return 1;
    return 0;
  }

  // Action methods
  void markAsPaid() {
    _isPaid = true;
  }

  void markAsUnpaid() {
    _isPaid = false;
  }

  void addNote(String note) {
    if (_notes == null || _notes!.isEmpty) {
      _notes = note;
    } else {
      _notes = '$_notes; $note';
    }
  }

  void printDetails() {
    print('─────────────────────────────');
    print('${getCategoryEmoji()} $_description');
    print('💰 ${getFormattedAmount()}');
    print('📁 $_category');
    print('📅 ${getFormattedDate()}');
    print('${_isPaid ? "✅" : "❌"} ${_isPaid ? "Paid" : "Unpaid"}');
    if (_notes != null && _notes!.isNotEmpty) {
      print('📝 $_notes');
    }
    print('🕒 ${getDaysAgo()} days ago');
  }
}

void main() {
  print('🏦 ENHANCED EXPENSE CLASS DEMO\n');

  var expenses = [
    Expense(description: 'Morning coffee', amount: 4.50, category: 'Food'),
    Expense(description: 'Uber to work', amount: 12.00, category: 'Transport'),
    Expense(description: 'Laptop', amount: 899.99, category: 'Shopping', isPaid: true),
    Expense(description: 'Groceries', amount: 127.50, category: 'Food', notes: 'Weekly shopping'),
  ];

  // Print all summaries
  print('SUMMARY:');
  for (var expense in expenses) {
    print(expense.getSummary());
  }

  // Calculate totals
  double total = 0;
  for (var expense in expenses) {
    total += expense.amount;
  }

  print('\n─────────────────────────────');
  print('Total: \$${total.toStringAsFixed(2)}');

  // Show percentages
  print('\nPERCENTAGES:');
  for (var expense in expenses) {
    print('${expense.description}: ${expense.getPercentageOf(total).toStringAsFixed(1)}%');
  }

  // Show this month's expenses
  print('\nTHIS MONTH:');
  for (var expense in expenses) {
    if (expense.isThisMonth()) {
      print(expense.getFullDisplay());
    }
  }

  // Show major expenses
  print('\nMAJOR EXPENSES (>\$100):');
  for (var expense in expenses) {
    if (expense.isMajorExpense()) {
      expense.printDetails();
    }
  }
}

Exercise 1: Time-Based Methods (Easy)

Add these methods to the Expense class:

  1. getWeekNumber() - returns the week number of the year
  2. getQuarter() - returns which quarter (1-4) the expense is in
  3. isWeekend() - returns true if expense was on Saturday or Sunday

Solution:

int getWeekNumber() {
  int dayOfYear = int.parse(DateFormat("D").format(_date));
  return ((dayOfYear - _date.weekday + 10) / 7).floor();
}

int getQuarter() {
  return ((_date.month - 1) / 3).floor() + 1;
}

bool isWeekend() {
  return _date.weekday == DateTime.saturday || _date.weekday == DateTime.sunday;
}

void main() {
  var expense = Expense(
    description: 'Weekend brunch',
    amount: 45.00,
    category: 'Food',
    date: DateTime(2025, 10, 11), // Saturday
  );

  print('Quarter: ${expense.getQuarter()}');
  print('Is weekend? ${expense.isWeekend()}');
}

Exercise 2: Statistical Methods (Medium)

Add these methods:

  1. getAmountRounded() - returns amount rounded to nearest dollar
  2. getDailyAverage(int days) - returns average per day over specified period
  3. projectedYearly() - if this was monthly, what would yearly total be?

Solution:

double getAmountRounded() {
  return _amount.roundToDouble();
}

double getDailyAverage(int days) {
  if (days <= 0) return 0;
  return _amount / days;
}

double projectedYearly() {
  return _amount * 12;
}

void main() {
  var subscription = Expense(
    description: 'Netflix',
    amount: 15.99,
    category: 'Entertainment',
  );

  print('Amount: ${subscription.getFormattedAmount()}');
  print('Rounded: \$${subscription.getAmountRounded().toStringAsFixed(2)}');
  print('Daily average (30 days): \$${subscription.getDailyAverage(30).toStringAsFixed(2)}');
  print('Projected yearly: \$${subscription.projectedYearly().toStringAsFixed(2)}');
}

Exercise 3: Smart Analysis Methods (Hard)

Create these advanced methods:

  1. getRiskLevel() - returns 'Low', 'Medium', or 'High' based on amount
  2. getSavingSuggestion() - returns a tip for reducing this expense
  3. compareToAverage(double avgExpense) - returns how much above/below average

Solution:

String getRiskLevel() {
  if (_amount < 50) return 'Low';
  if (_amount < 200) return 'Medium';
  return 'High';
}

String getSavingSuggestion() {
  if (_category == 'Food' && _amount > 50) {
    return 'Consider meal prepping to reduce food costs';
  }
  if (_category == 'Transport' && _amount > 100) {
    return 'Look into public transportation or carpooling';
  }
  if (_category == 'Entertainment' && _amount > 50) {
    return 'Try free entertainment options like parks or libraries';
  }
  if (_amount > 500) {
    return 'Major purchase - ensure it aligns with your budget goals';
  }
  return 'Expense looks reasonable';
}

String compareToAverage(double avgExpense) {
  double difference = _amount - avgExpense;
  double percentDiff = (difference / avgExpense * 100).abs();

  if (difference > 0) {
    return '\$${difference.toStringAsFixed(2)} (${percentDiff.toStringAsFixed(1)}%) above average';
  } else if (difference < 0) {
    return '\$${difference.abs().toStringAsFixed(2)} (${percentDiff.toStringAsFixed(1)}%) below average';
  } else {
    return 'Exactly average';
  }
}

void main() {
  var lunch = Expense(description: 'Lunch', amount: 85.00, category: 'Food');

  print('Risk level: ${lunch.getRiskLevel()}');
  print('Suggestion: ${lunch.getSavingSuggestion()}');
  print('vs Average: ${lunch.compareToAverage(50.0)}');
}

Mistake 1: Not Returning Values

// ❌ Wrong - method doesn't return anything
String getSummary() {
  '$_description: \$${_amount}';
}

// ✅ Correct - use return
String getSummary() {
  return '$_description: \$${_amount}';
}

Mistake 2: Forgetting to Handle Edge Cases

// ❌ Wrong - division by zero possible
double splitAmount(int numberOfPeople) {
  return _amount / numberOfPeople;
}

// ✅ Correct - check for invalid input
double splitAmount(int numberOfPeople) {
  if (numberOfPeople <= 0) return _amount;
  return _amount / numberOfPeople;
}

Mistake 3: Not Using Named Parameters When Appropriate

// ❌ Wrong - hard to remember order
String format(bool showDate, bool showCategory, bool showEmoji) { ... }

// ✅ Correct - use named parameters
String format({bool showDate = false, bool showCategory = true, bool showEmoji = false}) { ... }

Mistake 4: Making Methods Too Complex

// ❌ Wrong - doing too much
String doEverything() {
  // 100 lines of code doing multiple things
}

// ✅ Correct - separate concerns
String getSummary() { ... }
String getFormattedDate() { ... }
double calculateTotal() { ... }

Boolean methods return true/false for conditions

Formatting methods return nicely formatted strings

Calculation methods perform math and return results

Optional parameters make methods flexible

Comparison methods compare objects

Action methods modify object state

Keep methods focused - each does one thing well

1. When should you use a method vs a computed getter?

Answer:

  • Method: When there are parameters, complex logic, or side effects
  • Getter: For simple property access or calculations without parameters
  • Example: getTax(taxRate: 0.15) is a method, isMajorExpense is a getter

2. What's the benefit of optional parameters?

Answer:
Optional parameters make methods flexible - users can provide values when needed but use defaults otherwise. This reduces the need for multiple method versions.

3. Why should methods be focused on one task?

Answer:

  • Easier to understand and test
  • More reusable in different contexts
  • Simpler to debug when issues arise
  • Follows "Single Responsibility Principle"

In Lesson 6: Managing Multiple Expenses, we'll learn:

  • Creating an ExpenseManager class
  • Working with lists of expenses
  • Filtering and sorting
  • Calculating totals across multiple expenses
  • Building reports

Example preview:

class ExpenseManager {
  List<Expense> _expenses = [];

  void addExpense(Expense expense) { ... }
  double getTotalSpending() { ... }
  List<Expense> getByCategory(String category) { ... }
  List<Expense> getThisMonth() { ... }
  Expense? getLargestExpense() { ... }
}

See you in Lesson 6! 🚀

  • Try adding more methods to your Expense class
  • Think about what calculations would be useful for your app
  • Consider what formatting options users might want
  • Practice writing focused, single-purpose methods

Remember: Methods should make your objects useful and intelligent. Each method should do one thing well! 💪

Dart Object Oriented For Beginner : Expense Manager Case Study Part 4

Lesson 4: Protecting Your Data (Encapsulation)

Duration: 35 minutes

App Feature: 🔒 Making Sure Expenses Are Valid

What You'll Build: Add validation so users can't create invalid expenses

Prerequisites: Complete Lessons 1-3

By the end of this lesson, you'll be able to:

  • ✅ Make properties private to protect data
  • ✅ Use getters to read data safely
  • ✅ Use setters to validate data before saving
  • ✅ Prevent bugs like negative expenses or invalid categories
  • ✅ Understand why encapsulation matters

Let's look at our current Expense class:

class Expense {
  String description;
  double amount;
  String category;
  DateTime date;

  Expense(this.description, this.amount, this.category, this.date);
}

void main() {
  var coffee = Expense('Coffee', 4.50, 'Food', DateTime.now());

  // Uh oh... we can do this!
  coffee.amount = -100.50;  // Negative expense?!
  coffee.category = 'asdfgh';  // Invalid category!
  coffee.description = '';  // Empty description!

  print('Amount: \$${coffee.amount}');  // -$100.50 😱
}

Problems:

  1. ❌ Anyone can set amount to a negative number
  2. ❌ Invalid categories like "asdfgh" are allowed
  3. ❌ Empty descriptions are possible
  4. ❌ No way to validate data
  5. ❌ Easy to create bugs

What we need: A way to protect our data and validate it before accepting changes!

In Dart, you make something private by adding an underscore _ prefix:

class Expense {
  String _description;  // Private - can't access from outside
  double _amount;       // Private
  String _category;     // Private
  DateTime _date;       // Private

  Expense(this._description, this._amount, this._category, this._date);
}

void main() {
  var coffee = Expense('Coffee', 4.50, 'Food', DateTime.now());

  // ❌ ERROR! These don't work anymore
  // coffee._amount = -100;
  // print(coffee._description);

  // Private properties can't be accessed from outside the class
}

Understanding Private Properties:

String _description;  // Underscore = private
  • Can only be accessed inside the class
  • Protected from outside modification
  • No one can directly change the value

But wait... If everything is private, how do we read or change values? 🤔

Getters let you read private data in a controlled way:

class Expense {
  String _description;
  double _amount;
  String _category;
  DateTime _date;

  Expense(this._description, this._amount, this._category, this._date);

  // Getters - read-only access
  String get description => _description;
  double get amount => _amount;
  String get category => _category;
  DateTime get date => _date;
}

void main() {
  var coffee = Expense('Coffee', 4.50, 'Food', DateTime.now());

  // ✅ Can read using getters
  print('Description: ${coffee.description}');
  print('Amount: \$${coffee.amount}');

  // ❌ But can't modify directly
  // coffee.amount = -100;  // ERROR!
}

Understanding Getter Syntax:

double get amount => _amount;
  • double = return type
  • get = keyword for getter
  • amount = getter name (no underscore!)
  • => = arrow function (shorthand)
  • _amount = returns the private property

Alternative syntax (with function body):

double get amount {
  return _amount;
}

Both work the same way!

Setters let you change private data, but with validation:

class Expense {
  String _description;
  double _amount;
  String _category;
  DateTime _date;

  Expense(this._description, this._amount, this._category, this._date);

  // Getters
  String get description => _description;
  double get amount => _amount;
  String get category => _category;
  DateTime get date => _date;

  // Setters with validation
  set amount(double value) {
    if (value < 0) {
      print('❌ Error: Amount cannot be negative!');
      return;  // Don't change the value
    }
    _amount = value;
  }

  set description(String value) {
    if (value.trim().isEmpty) {
      print('❌ Error: Description cannot be empty!');
      return;
    }
    _description = value;
  }

  set category(String value) {
    List<String> validCategories = [
      'Food', 
      'Transport', 
      'Bills', 
      'Entertainment', 
      'Health',
      'Shopping',
      'Other'
    ];

    if (!validCategories.contains(value)) {
      print('❌ Error: Invalid category "$value". Using "Other".');
      _category = 'Other';
      return;
    }
    _category = value;
  }
}

void main() {
  var coffee = Expense('Coffee', 4.50, 'Food', DateTime.now());

  // ✅ Valid changes work
  coffee.amount = 5.00;
  print('New amount: \$${coffee.amount}');

  // ❌ Invalid changes are rejected
  coffee.amount = -10;  // Prints error, doesn't change
  print('Amount still: \$${coffee.amount}');  // Still 5.00

  coffee.description = '';  // Prints error, doesn't change
  coffee.category = 'InvalidCategory';  // Changes to 'Other'
}

Output:

New amount: $5.00
❌ Error: Amount cannot be negative!
Amount still: $5.00
❌ Error: Description cannot be empty!
❌ Error: Invalid category "InvalidCategory". Using "Other".

Understanding Setter Syntax:

set amount(double value) {
  if (value < 0) {
    print('❌ Error: Amount cannot be negative!');
    return;
  }
  _amount = value;
}
  • set = keyword for setter
  • amount = setter name (matches getter name)
  • (double value) = the new value being set
  • Validate before setting _amount
  • return early if invalid

We should also validate when creating an expense:

class Expense {
  String _description;
  double _amount;
  String _category;
  DateTime _date;

  Expense(String description, double amount, String category, DateTime date)
    : _description = description,
      _amount = amount,
      _category = category,
      _date = date {
    // Validate in constructor body
    if (_amount < 0) {
      throw Exception('Amount cannot be negative!');
    }
    if (_description.trim().isEmpty) {
      throw Exception('Description cannot be empty!');
    }

    List<String> validCategories = [
      'Food', 'Transport', 'Bills', 'Entertainment', 'Health', 'Shopping', 'Other'
    ];
    if (!validCategories.contains(_category)) {
      print('⚠️ Warning: Invalid category "$_category". Changed to "Other".');
      _category = 'Other';
    }
  }

  // Getters
  String get description => _description;
  double get amount => _amount;
  String get category => _category;
  DateTime get date => _date;

  // Setters
  set amount(double value) {
    if (value < 0) {
      print('❌ Error: Amount cannot be negative!');
      return;
    }
    _amount = value;
  }

  set category(String value) {
    List<String> validCategories = [
      'Food', 'Transport', 'Bills', 'Entertainment', 'Health', 'Shopping', 'Other'
    ];
    if (!validCategories.contains(value)) {
      print('❌ Error: Invalid category. Using "Other".');
      _category = 'Other';
      return;
    }
    _category = value;
  }
}

void main() {
  try {
    var invalid = Expense('', -50, 'Food', DateTime.now());
  } catch (e) {
    print('Failed to create expense: $e');
  }

  // This works but changes category
  var expense = Expense('Coffee', 4.50, 'InvalidCat', DateTime.now());
  print('Category: ${expense.category}');  // 'Other'
}

Getters can also calculate values on-the-fly:

class Expense {
  String _description;
  double _amount;
  String _category;
  DateTime _date;

  Expense(this._description, this._amount, this._category, this._date) {
    if (_amount < 0) throw Exception('Amount cannot be negative!');
  }

  // Regular getters
  String get description => _description;
  double get amount => _amount;
  String get category => _category;
  DateTime get date => _date;

  // Computed getters - calculate on the fly
  bool get isMajorExpense => _amount > 100;

  bool get isThisMonth {
    DateTime now = DateTime.now();
    return _date.year == now.year && _date.month == now.month;
  }

  String get formattedAmount => '\$${_amount.toStringAsFixed(2)}';

  String get formattedDate => _date.toString().split(' ')[0];

  int get daysAgo => DateTime.now().difference(_date).inDays;

  String get summary => '$_description: $formattedAmount [$_category]';

  // Emoji based on amount
  String get categoryEmoji {
    switch (_category) {
      case 'Food': return '🍔';
      case 'Transport': return '🚗';
      case 'Bills': return '💡';
      case 'Entertainment': return '🎬';
      case 'Health': return '💊';
      case 'Shopping': return '🛍️';
      default: return '📝';
    }
  }
}

void main() {
  var coffee = Expense('Coffee', 4.50, 'Food', DateTime.now());
  var laptop = Expense('Laptop', 899.99, 'Shopping', DateTime(2025, 10, 5));

  print(coffee.summary);
  print('Is major? ${coffee.isMajorExpense}');
  print('Days ago: ${coffee.daysAgo}');
  print('${coffee.categoryEmoji} ${coffee.category}');

  print('\n${laptop.summary}');
  print('Is major? ${laptop.isMajorExpense}');
  print('${laptop.categoryEmoji} ${laptop.category}');
}

Output:

Coffee: $4.50 [Food]
Is major? false
Days ago: 0
🍔 Food

Laptop: $899.99 [Shopping]
Is major? true
🛍️ Shopping

Here's a production-ready Expense class with full encapsulation:

class Expense {
  // Private properties
  String _description;
  double _amount;
  String _category;
  DateTime _date;
  String? _notes;
  bool _isPaid;

  // Valid categories list
  static const List<String> validCategories = [
    'Food',
    'Transport',
    'Bills',
    'Entertainment',
    'Health',
    'Shopping',
    'Other',
  ];

  // Constructor with validation
  Expense({
    required String description,
    required double amount,
    required String category,
    DateTime? date,
    String? notes,
    bool isPaid = false,
  }) : _description = description,
       _amount = amount,
       _category = category,
       _date = date ?? DateTime.now(),
       _notes = notes,
       _isPaid = isPaid {
    // Validate amount
    if (_amount < 0) {
      throw Exception('Amount cannot be negative');
    }

    // Validate description
    if (_description.trim().isEmpty) {
      throw Exception('Description cannot be empty');
    }

    // Validate category
    if (!validCategories.contains(_category)) {
      print('⚠️ Invalid category "$_category". Changed to "Other".');
      _category = 'Other';
    }
  }

  // Named constructor
  Expense.quick(String description, double amount, String category)
    : this(description: description, amount: amount, category: category);

  // Getters (read-only)
  String get description => _description;
  double get amount => _amount;
  String get category => _category;
  DateTime get date => _date;
  String? get notes => _notes;
  bool get isPaid => _isPaid;

  // Computed getters
  bool get isMajorExpense => _amount > 100;
  String get formattedAmount => '\$${_amount.toStringAsFixed(2)}';
  String get formattedDate => _date.toString().split(' ')[0];

  String get categoryEmoji {
    switch (_category) {
      case 'Food': return '🍔';
      case 'Transport': return '🚗';
      case 'Bills': return '💡';
      case 'Entertainment': return '🎬';
      case 'Health': return '💊';
      case 'Shopping': return '🛍️';
      default: return '📝';
    }
  }

  // Setters with validation
  set amount(double value) {
    if (value < 0) {
      throw Exception('Amount cannot be negative');
    }
    _amount = value;
  }

  set description(String value) {
    if (value.trim().isEmpty) {
      throw Exception('Description cannot be empty');
    }
    _description = value.trim();
  }

  set category(String value) {
    if (!validCategories.contains(value)) {
      throw Exception('Invalid category: $value');
    }
    _category = value;
  }

  set notes(String? value) {
    _notes = value;
  }

  set isPaid(bool value) {
    _isPaid = value;
  }

  // Methods
  void markAsPaid() {
    _isPaid = true;
    print('✅ Marked as paid: $_description');
  }

  void markAsUnpaid() {
    _isPaid = false;
    print('❌ Marked as unpaid: $_description');
  }

  void addNote(String note) {
    if (_notes == null || _notes!.isEmpty) {
      _notes = note;
    } else {
      _notes = '$_notes; $note';
    }
  }

  void printDetails() {
    String paidStatus = _isPaid ? '✅ Paid' : '❌ Unpaid';
    String noteText = _notes != null ? '\n   📝 $_notes' : '';

    print('─────────────────────────────');
    print('$categoryEmoji $_description');
    print('💰 $formattedAmount');
    print('📁 $_category');
    print('📅 $formattedDate');
    print('$paidStatus$noteText');
  }
}

void main() {
  print('🏦 EXPENSE MANAGER WITH VALIDATION\n');

  // Create valid expenses
  var coffee = Expense.quick('Morning coffee', 4.50, 'Food');
  var rent = Expense(
    description: 'Monthly rent',
    amount: 1200.0,
    category: 'Bills',
    isPaid: true,
  );

  coffee.printDetails();
  print('');
  rent.printDetails();

  print('\n📝 TESTING VALIDATION:\n');

  // Test setters
  print('Changing coffee amount to 5.00...');
  coffee.amount = 5.00;
  print('✅ Success! New amount: ${coffee.formattedAmount}');

  try {
    print('\nTrying to set negative amount...');
    coffee.amount = -10;
  } catch (e) {
    print('❌ Caught error: $e');
  }

  try {
    print('\nTrying to set empty description...');
    coffee.description = '';
  } catch (e) {
    print('❌ Caught error: $e');
  }

  try {
    print('\nTrying invalid category...');
    coffee.category = 'InvalidCategory';
  } catch (e) {
    print('❌ Caught error: $e');
  }

  print('\n✅ Adding valid note...');
  coffee.addNote('Bought at Starbucks');
  coffee.printDetails();
}

Real-World Benefits:

1. Data Integrity 🛡️

// Without encapsulation - bugs everywhere!
expense.amount = -999;  // Oops!
expense.category = 'asfgh';  // Typo!

// With encapsulation - protected!
expense.amount = -999;  // ❌ Throws error
expense.category = 'asfgh';  // ❌ Throws error

2. Easier Debugging 🐛

// Without encapsulation - amount changes everywhere
// Where did the bug come from? No idea!

// With encapsulation - only through setters
// Search for "set amount" to find where it changes

3. Future Changes 🔄

// Need to change how amount is stored?
// With encapsulation, change internal code only
// External code using getters/setters keeps working!

class Expense {
  int _amountInCents;  // Changed storage format

  double get amount => _amountInCents / 100;  // Convert on read
  set amount(double value) => _amountInCents = (value * 100).round();
}

4. Business Rules 📋

// Enforce business logic in one place
set amount(double value) {
  if (value < 0) throw Exception('Negative amount');
  if (value > 10000) {
    print('⚠️ Large amount! Requires approval.');
  }
  _amount = value;
}

Exercise 1: Protected Category Class (Easy)

Create a Category class with:

  • Private properties: _name, _icon, _budget
  • Getters for all properties
  • Setter for budget that only allows positive values
  • Computed getter isOverBudget(double spent) that returns true if spent > budget

Solution:

class Category {
  String _name;
  String _icon;
  double _budget;

  Category(this._name, this._icon, this._budget) {
    if (_budget < 0) {
      throw Exception('Budget cannot be negative');
    }
  }

  // Getters
  String get name => _name;
  String get icon => _icon;
  double get budget => _budget;

  // Setter with validation
  set budget(double value) {
    if (value < 0) {
      throw Exception('Budget cannot be negative');
    }
    _budget = value;
  }

  // Method
  bool isOverBudget(double spent) {
    return spent > _budget;
  }

  void printStatus(double spent) {
    String status = isOverBudget(spent) ? '❌ Over budget!' : '✅ Within budget';
    print('$_icon $_name: \$${spent.toStringAsFixed(2)} / \$${_budget.toStringAsFixed(2)} - $status');
  }
}

void main() {
  var food = Category('Food', '🍔', 500.0);

  food.printStatus(350.0);  // Within budget
  food.printStatus(550.0);  // Over budget

  // Test validation
  try {
    food.budget = -100;
  } catch (e) {
    print('Error: $e');
  }
}

Exercise 2: Smart User Class (Medium)

Create a User class with:

  • Private: _name, _email, _age
  • Validate email must contain '@'
  • Validate age must be between 13 and 120
  • Computed getter isAdult (age >= 18)
  • Computed getter displayName (name + age category)

Solution:

class User {
  String _name;
  String _email;
  int _age;

  User({
    required String name,
    required String email,
    required int age,
  }) : _name = name,
       _email = email,
       _age = age {
    if (!_email.contains('@')) {
      throw Exception('Invalid email format');
    }
    if (_age < 13 || _age > 120) {
      throw Exception('Age must be between 13 and 120');
    }
  }

  // Getters
  String get name => _name;
  String get email => _email;
  int get age => _age;

  // Computed getters
  bool get isAdult => _age >= 18;

  String get ageCategory {
    if (_age < 18) return 'Minor';
    if (_age < 65) return 'Adult';
    return 'Senior';
  }

  String get displayName => '$_name ($ageCategory, $_age)';

  // Setters with validation
  set email(String value) {
    if (!value.contains('@')) {
      throw Exception('Invalid email format');
    }
    _email = value;
  }

  set age(int value) {
    if (value < 13 || value > 120) {
      throw Exception('Age must be between 13 and 120');
    }
    _age = value;
  }

  void printProfile() {
    print('👤 $displayName');
    print('📧 $_email');
    print('Status: ${isAdult ? "Adult ✅" : "Minor ❌"}');
  }
}

void main() {
  var user = User(name: 'John Doe', email: 'john@example.com', age: 25);
  user.printProfile();

  print('\n--- Testing validation ---');

  try {
    user.email = 'invalidemail';
  } catch (e) {
    print('❌ $e');
  }

  try {
    user.age = 150;
  } catch (e) {
    print('❌ $e');
  }
}

Exercise 3: Bank Account Class (Hard)

Create a BankAccount class with:

  • Private: _accountHolder, _balance, _pin
  • Methods: deposit(amount), withdraw(amount, pin)
  • Cannot withdraw without correct PIN
  • Cannot withdraw more than balance
  • Cannot deposit negative amounts
  • Getter for balance (but not setter!)
  • Method changePin(oldPin, newPin)

Solution:

class BankAccount {
  String _accountHolder;
  double _balance;
  String _pin;

  BankAccount({
    required String accountHolder,
    required String pin,
    double initialBalance = 0,
  }) : _accountHolder = accountHolder,
       _pin = pin,
       _balance = initialBalance {
    if (_pin.length != 4) {
      throw Exception('PIN must be 4 digits');
    }
    if (_balance < 0) {
      throw Exception('Initial balance cannot be negative');
    }
  }

  // Getters
  String get accountHolder => _accountHolder;
  double get balance => _balance;  // Read-only, no setter!

  // Deposit method
  void deposit(double amount) {
    if (amount <= 0) {
      print('❌ Deposit amount must be positive');
      return;
    }
    _balance += amount;
    print('✅ Deposited \$${amount.toStringAsFixed(2)}. New balance: \$${_balance.toStringAsFixed(2)}');
  }

  // Withdraw method with PIN validation
  bool withdraw(double amount, String pin) {
    if (pin != _pin) {
      print('❌ Incorrect PIN');
      return false;
    }

    if (amount <= 0) {
      print('❌ Withdrawal amount must be positive');
      return false;
    }

    if (amount > _balance) {
      print('❌ Insufficient funds. Balance: \$${_balance.toStringAsFixed(2)}');
      return false;
    }

    _balance -= amount;
    print('✅ Withdrew \$${amount.toStringAsFixed(2)}. New balance: \$${_balance.toStringAsFixed(2)}');
    return true;
  }

  // Change PIN
  bool changePin(String oldPin, String newPin) {
    if (oldPin != _pin) {
      print('❌ Incorrect old PIN');
      return false;
    }

    if (newPin.length != 4) {
      print('❌ New PIN must be 4 digits');
      return false;
    }

    _pin = newPin;
    print('✅ PIN changed successfully');
    return true;
  }

  void printStatement() {
    print('─────────────────────────────');
    print('Account Holder: $_accountHolder');
    print('Balance: \$${_balance.toStringAsFixed(2)}');
    print('─────────────────────────────');
  }
}

void main() {
  var account = BankAccount(
    accountHolder: 'John Doe',
    pin: '1234',
    initialBalance: 1000.0,
  );

  account.printStatement();

  print('\n--- Transactions ---');
  account.deposit(500.0);
  account.withdraw(200.0, '1234');
  account.withdraw(200.0, '0000');  // Wrong PIN
  account.withdraw(2000.0, '1234');  // Insufficient funds

  print('\n--- Change PIN ---');
  account.changePin('0000', '5678');  // Wrong old PIN
  account.changePin('1234', '5678');  // Success

  print('');
  account.printStatement();
}

Mistake 1: Forgetting the Underscore

// ❌ Wrong - not private
String description;

// ✅ Correct - private
String _description;

Mistake 2: Making Getter and Setter Names Different

// ❌ Wrong - names don't match
double get amount => _amount;
set setAmount(double value) { _amount = value; }

// ✅ Correct - same name
double get amount => _amount;
set amount(double value) { _amount = value; }

Mistake 3: Forgetting Validation

// ❌ Wrong - no validation
set amount(double value) {
  _amount = value;
}

// ✅ Correct - validate first
set amount(double value) {
  if (value < 0) {
    throw Exception('Amount cannot be negative');
  }
  _amount = value;
}

Mistake 4: Direct Access to Private Properties Outside Class

// ❌ Wrong - trying to access private property
print(expense._amount);

// ✅ Correct - use getter
print(expense.amount);

Private properties use underscore _ prefix

Getters provide read access with get keyword

Setters provide write access with set keyword and validation

Validation prevents invalid data from entering your objects

Encapsulation protects data and enforces business rules

Computed getters calculate values on-the-fly

Data integrity is maintained through controlled access

1. What does encapsulation mean?

Answer:
Encapsulation means hiding internal data and providing controlled access through getters and setters. It protects data from invalid changes and enforces business rules.

2. Why use getters and setters instead of public properties?

Answer:

  • Validate data before accepting changes
  • Prevent invalid states (like negative amounts)
  • Can change internal implementation without breaking external code
  • Enforce business rules in one place
  • Better debugging (know where data changes)

3. What's the difference between a regular getter and a computed getter?

Answer:

  • Regular getter: Returns a stored private property (get amount => _amount)
  • Computed getter: Calculates a value on-the-fly (get isAdult => _age >= 18)

In Lesson 5: Adding Useful Features, we'll learn:

  • More advanced methods for our Expense class
  • Working with lists of expenses
  • Filtering and sorting
  • Calculating totals and statistics
  • Building helper methods

Example preview:

class ExpenseManager {
  List<Expense> _expenses = [];

  void addExpense(Expense expense) { ... }
  double getTotalSpending() { ... }
  List<Expense> getByCategory(String category) { ... }
  Expense? getLargestExpense() { ... }
}

See you in Lesson 5! 🚀

  • Practice creating other protected classes: CreditCard, Budget, UserProfile
  • Think about what data should be protected in a real app
  • Consider what validation rules make sense for your expense manager

Remember: Encapsulation isn't about making everything private - it's about protecting data that needs protection and providing safe ways to interact with it! 🔒

Dart Object Oriented For Beginner : Expense Manager Case Study Part 3

Lesson 3: Different Ways to Create Expenses

Duration: 25 minutes

App Feature: 🔧 Making Expense Creation Easier

What You'll Build: Add multiple ways to create expenses with constructors

Prerequisites: Complete Lesson 1 & 2

By the end of this lesson, you'll be able to:

  • ✅ Create named constructors for easier object creation
  • ✅ Use optional parameters
  • ✅ Set default values
  • ✅ Build multiple constructor variations
  • ✅ Make your code more flexible and user-friendly

In Lesson 2, we learned the basic constructor:

class Expense {
  String description;
  double amount;
  String category;
  DateTime date;

  Expense(this.description, this.amount, this.category, this.date);
}

void main() {
  var coffee = Expense('Coffee', 4.50, 'Food', DateTime.now());
}

The Problem: Every time we create an expense, we need to provide ALL four values. But what if:

  • Most expenses are from today? (we always type DateTime.now())
  • We want quick shortcuts for common scenarios?
  • Some values have sensible defaults?

The Solution: Named constructors and optional parameters!

A named constructor is an alternative way to create objects. You can have multiple constructors in one class, each with a different name.

Syntax:

ClassName.constructorName(parameters)

Example: Quick Expense Constructor

class Expense {
  String description;
  double amount;
  String category;
  DateTime date;

  // Regular constructor
  Expense(this.description, this.amount, this.category, this.date);

  // Named constructor - assumes today's date
  Expense.quick(this.description, this.amount, this.category) 
    : date = DateTime.now();
}

void main() {
  // Using regular constructor
  var laptop = Expense('Laptop', 899.99, 'Electronics', DateTime(2025, 10, 5));

  // Using named constructor - much shorter!
  var coffee = Expense.quick('Coffee', 4.50, 'Food');
  var lunch = Expense.quick('Lunch', 12.75, 'Food');

  print('${coffee.description}: \$${coffee.amount} on ${coffee.date}');
}

Understanding the Syntax:

Expense.quick(this.description, this.amount, this.category) 
  : date = DateTime.now();
  • Expense.quick = class name + dot + constructor name
  • Parameters in () work like normal constructor
  • : date = DateTime.now() is the initializer list
  • Sets date property before the object is fully created

Let's add several named constructors for common scenarios:

class Expense {
  String description;
  double amount;
  String category;
  DateTime date;

  // 1. Regular constructor - full control
  Expense(this.description, this.amount, this.category, this.date);

  // 2. Quick constructor - assumes today
  Expense.quick(this.description, this.amount, this.category) 
    : date = DateTime.now();

  // 3. Monthly bill constructor - assumes "Bills" category
  Expense.monthly(this.description, this.amount) 
    : category = 'Bills',
      date = DateTime.now();

  // 4. Yesterday constructor - for when you forget to log
  Expense.yesterday(this.description, this.amount, this.category) 
    : date = DateTime.now().subtract(Duration(days: 1));

  void printDetails() {
    print('$description: \$${amount.toStringAsFixed(2)} [$category] on ${date.toString().split(' ')[0]}');
  }
}

void main() {
  print('MY EXPENSES:\n');

  // Using different constructors
  var rent = Expense.monthly('Rent', 1200.0);
  var coffee = Expense.quick('Coffee', 4.50, 'Food');
  var dinner = Expense.yesterday('Dinner', 35.00, 'Food');
  var vacation = Expense('Flight', 450.0, 'Travel', DateTime(2025, 12, 20));

  rent.printDetails();
  coffee.printDetails();
  dinner.printDetails();
  vacation.printDetails();
}

Output:

MY EXPENSES:

Rent: $1200.00 [Bills] on 2025-10-09
Coffee: $4.50 [Food] on 2025-10-09
Dinner: $35.00 [Food] on 2025-10-08
Flight: $450.00 [Travel] on 2025-12-20

You can set multiple properties in the initializer list:

class Expense {
  String description;
  double amount;
  String category;
  DateTime date;

  Expense(this.description, this.amount, this.category, this.date);

  // Initialize BOTH category and date
  Expense.subscription(this.description, this.amount) 
    : category = 'Entertainment',
      date = DateTime.now();

  // Initialize with calculations
  Expense.weekly(this.description, double weeklyAmount) 
    : amount = weeklyAmount * 52,  // Convert to yearly
      category = 'Recurring',
      date = DateTime.now();
}

void main() {
  var netflix = Expense.subscription('Netflix', 15.99);
  var coffee = Expense.weekly('Coffee habit', 25.00);  // $25/week

  netflix.printDetails();
  print('Coffee yearly: \$${coffee.amount.toStringAsFixed(2)}');
}

Key Points:

  • Separate multiple initializations with commas
  • Can include calculations or method calls
  • Runs BEFORE the constructor body (if you have one)

Sometimes you want parameters that are... optional! Dart has two ways to do this:

A. Optional Positional Parameters (with [])

class Expense {
  String description;
  double amount;
  String category;
  DateTime date;
  String? notes;  // Nullable - can be null

  // Optional positional parameters in square brackets
  Expense(this.description, this.amount, this.category, [DateTime? date, this.notes]) 
    : date = date ?? DateTime.now();  // Use provided date OR current date
}

void main() {
  // With date and notes
  var expense1 = Expense('Laptop', 899.99, 'Electronics', DateTime(2025, 10, 5), 'Work laptop');

  // Without date (uses today)
  var expense2 = Expense('Coffee', 4.50, 'Food');

  // With date but no notes
  var expense3 = Expense('Dinner', 45.00, 'Food', DateTime(2025, 10, 8));
}

Understanding ?? operator:

  • date ?? DateTime.now() means: "use date if provided, otherwise use DateTime.now()"
  • This is called the "null-aware" operator

B. Named Optional Parameters (with {})

Named parameters are more readable and can be provided in any order:

class Expense {
  String description;
  double amount;
  String category;
  DateTime date;
  String? notes;
  bool isPaid;

  // Named optional parameters in curly braces
  Expense({
    required this.description,
    required this.amount,
    required this.category,
    DateTime? date,
    this.notes,
    this.isPaid = false,  // Default value
  }) : date = date ?? DateTime.now();
}

void main() {
  // Can provide parameters in any order
  var expense1 = Expense(
    amount: 45.00,
    description: 'Dinner',
    category: 'Food',
    notes: 'Birthday dinner',
    isPaid: true,
  );

  // Can skip optional parameters
  var expense2 = Expense(
    description: 'Coffee',
    amount: 4.50,
    category: 'Food',
  );

  // Can provide date if needed
  var expense3 = Expense(
    description: 'Rent',
    amount: 1200.0,
    category: 'Bills',
    date: DateTime(2025, 10, 1),
  );
}

Key Differences:

Feature Positional [] Named {}
Order matters ✅ Yes ❌ No
More readable ❌ Less ✅ More
Can be required ❌ No ✅ Yes (with required)
Default values ✅ Yes ✅ Yes

You can provide default values for optional parameters:

class Expense {
  String description;
  double amount;
  String category;
  DateTime date;
  String currency;
  bool isPaid;

  Expense({
    required this.description,
    required this.amount,
    this.category = 'Other',        // Default: 'Other'
    DateTime? date,
    this.currency = 'USD',           // Default: 'USD'
    this.isPaid = false,             // Default: false
  }) : date = date ?? DateTime.now();

  void printDetails() {
    String paidStatus = isPaid ? '✅ Paid' : '❌ Unpaid';
    print('$description: $currency \$${amount.toStringAsFixed(2)} [$category] - $paidStatus');
  }
}

void main() {
  // Using all defaults
  var expense1 = Expense(
    description: 'Mystery purchase',
    amount: 25.00,
  );

  // Override some defaults
  var expense2 = Expense(
    description: 'Rent',
    amount: 1200.0,
    category: 'Bills',
    isPaid: true,
  );

  // Override currency
  var expense3 = Expense(
    description: 'Tokyo hotel',
    amount: 15000,
    currency: 'JPY',
    category: 'Travel',
  );

  expense1.printDetails();
  expense2.printDetails();
  expense3.printDetails();
}

Output:

Mystery purchase: USD $25.00 [Other] - ❌ Unpaid
Rent: USD $1200.00 [Bills] - ✅ Paid
Tokyo hotel: JPY $15000.00 [Travel] - ❌ Unpaid

The most powerful approach combines both techniques:

class Expense {
  String description;
  double amount;
  String category;
  DateTime date;
  String? notes;
  bool isPaid;

  // Regular constructor with named parameters
  Expense({
    required this.description,
    required this.amount,
    required this.category,
    DateTime? date,
    this.notes,
    this.isPaid = false,
  }) : date = date ?? DateTime.now();

  // Named constructor: quick expense (today, unpaid)
  Expense.quick(
    this.description,
    this.amount,
    this.category, {
    this.notes,
  }) : date = DateTime.now(),
       isPaid = false;

  // Named constructor: monthly bill (bills category, today, paid)
  Expense.bill(
    this.description,
    this.amount, {
    this.notes,
  }) : category = 'Bills',
       date = DateTime.now(),
       isPaid = true;

  // Named constructor: recurring subscription
  Expense.subscription({
    required this.description,
    required this.amount,
    this.notes,
  }) : category = 'Entertainment',
       date = DateTime.now(),
       isPaid = true;

  void printDetails() {
    String paid = isPaid ? '✅' : '❌';
    String noteText = notes != null ? ' - $notes' : '';
    print('$paid $description: \$${amount.toStringAsFixed(2)} [$category]$noteText');
  }
}

void main() {
  print('OCTOBER EXPENSES:\n');

  // Different ways to create expenses
  var coffee = Expense.quick('Coffee', 4.50, 'Food');

  var rent = Expense.bill('Rent', 1200.0, notes: 'October payment');

  var netflix = Expense.subscription(
    description: 'Netflix',
    amount: 15.99,
    notes: 'Premium plan',
  );

  var dinner = Expense(
    description: 'Dinner date',
    amount: 85.50,
    category: 'Food',
    notes: 'Anniversary',
  );

  coffee.printDetails();
  rent.printDetails();
  netflix.printDetails();
  dinner.printDetails();
}

Output:

OCTOBER EXPENSES:

❌ Coffee: $4.50 [Food]
✅ Rent: $1200.00 [Bills] - October payment
✅ Netflix: $15.99 [Entertainment] - Premium plan
❌ Dinner date: $85.50 [Food] - Anniversary

Here's a production-ready Expense class with multiple constructors:

class Expense {
  String description;
  double amount;
  String category;
  DateTime date;
  String? notes;
  bool isPaid;
  String paymentMethod;

  // Main constructor - full control
  Expense({
    required this.description,
    required this.amount,
    required this.category,
    DateTime? date,
    this.notes,
    this.isPaid = false,
    this.paymentMethod = 'Cash',
  }) : date = date ?? DateTime.now();

  // Quick daily expense
  Expense.quick(
    this.description,
    this.amount,
    this.category,
  ) : date = DateTime.now(),
      notes = null,
      isPaid = false,
      paymentMethod = 'Cash';

  // Monthly recurring bill
  Expense.monthlyBill(
    this.description,
    this.amount, {
    this.paymentMethod = 'Auto-pay',
  }) : category = 'Bills',
       date = DateTime.now(),
       notes = 'Monthly recurring',
       isPaid = true;

  // Credit card purchase
  Expense.creditCard(
    this.description,
    this.amount,
    this.category, {
    this.notes,
  }) : date = DateTime.now(),
       isPaid = false,
       paymentMethod = 'Credit Card';

  // Cash purchase (already paid)
  Expense.cash(
    this.description,
    this.amount,
    this.category, {
    this.notes,
  }) : date = DateTime.now(),
       isPaid = true,
       paymentMethod = 'Cash';

  // Yesterday's expense (for when you forget to log)
  Expense.yesterday(
    this.description,
    this.amount,
    this.category,
  ) : date = DateTime.now().subtract(Duration(days: 1)),
      notes = 'Logged late',
      isPaid = true,
      paymentMethod = 'Cash';

  void printDetails() {
    String paid = isPaid ? '✅ Paid' : '❌ Unpaid';
    String noteText = notes != null ? '\n   Note: $notes' : '';
    print('─────────────────────────────');
    print('$description');
    print('Amount: \$${amount.toStringAsFixed(2)}');
    print('Category: $category');
    print('Date: ${date.toString().split(' ')[0]}');
    print('Payment: $paymentMethod');
    print('Status: $paid$noteText');
  }

  bool isMajorExpense() => amount > 100;

  String getSummary() {
    String emoji = isMajorExpense() ? '🔴' : '🟢';
    return '$emoji \$${amount.toStringAsFixed(2)} - $description [$category]';
  }
}

void main() {
  print('📊 EXPENSE TRACKER\n');

  var expenses = [
    Expense.quick('Morning coffee', 4.50, 'Food'),
    Expense.monthlyBill('Internet', 59.99),
    Expense.creditCard('Groceries', 127.50, 'Food', notes: 'Weekly shopping'),
    Expense.cash('Parking', 5.00, 'Transport'),
    Expense.yesterday('Lunch', 15.00, 'Food'),
    Expense(
      description: 'New laptop',
      amount: 1299.99,
      category: 'Electronics',
      paymentMethod: 'Credit Card',
      notes: 'Work equipment',
    ),
  ];

  // Print all summaries
  print('Summary:');
  for (var expense in expenses) {
    print(expense.getSummary());
  }

  // Print details of major expenses
  print('\n\nMAJOR EXPENSES (>\$100):');
  for (var expense in expenses) {
    if (expense.isMajorExpense()) {
      expense.printDetails();
    }
  }

  // Calculate totals
  double total = 0;
  double unpaid = 0;

  for (var expense in expenses) {
    total += expense.amount;
    if (!expense.isPaid) {
      unpaid += expense.amount;
    }
  }

  print('\n─────────────────────────────');
  print('💰 Total Expenses: \$${total.toStringAsFixed(2)}');
  print('❌ Unpaid: \$${unpaid.toStringAsFixed(2)}');
  print('✅ Paid: \$${(total - unpaid).toStringAsFixed(2)}');
}

Exercise 1: Create a Budget Class (Easy)

Create a Budget class with:

  • Properties: category, limit, month, year
  • Regular constructor
  • Named constructor Budget.monthly(category, limit) that uses current month/year

Solution:

class Budget {
  String category;
  double limit;
  int month;
  int year;

  Budget(this.category, this.limit, this.month, this.year);

  Budget.monthly(this.category, this.limit)
    : month = DateTime.now().month,
      year = DateTime.now().year;

  void printDetails() {
    print('$category: \$${limit.toStringAsFixed(2)} for $month/$year');
  }
}

void main() {
  var foodBudget = Budget.monthly('Food', 500.0);
  var rentBudget = Budget('Rent', 1200.0, 10, 2025);

  foodBudget.printDetails();
  rentBudget.printDetails();
}

Exercise 2: Enhanced Expense Creation (Medium)

Add these named constructors to your Expense class:

  1. Expense.splitBill(description, totalAmount, numberOfPeople) - divides amount by number of people
  2. Expense.tip(description, baseAmount, tipPercent) - calculates total with tip
  3. Expense.recurring(description, amount, frequency) - where frequency is 'weekly', 'monthly', or 'yearly'

Solution:

class Expense {
  String description;
  double amount;
  String category;
  DateTime date;
  String? notes;

  Expense(this.description, this.amount, this.category, this.date, {this.notes});

  // Split bill constructor
  Expense.splitBill(
    String desc,
    double totalAmount,
    int people,
  ) : description = '$desc (split $people ways)',
      amount = totalAmount / people,
      category = 'Food',
      date = DateTime.now(),
      notes = 'Split with $people people';

  // Tip calculator constructor
  Expense.tip(
    String desc,
    double baseAmount,
    double tipPercent,
  ) : description = desc,
      amount = baseAmount * (1 + tipPercent / 100),
      category = 'Food',
      date = DateTime.now(),
      notes = '${tipPercent}% tip included';

  // Recurring expense constructor
  Expense.recurring(
    this.description,
    this.amount,
    String frequency,
  ) : category = 'Bills',
      date = DateTime.now(),
      notes = 'Recurring: $frequency';
}

void main() {
  var dinner = Expense.splitBill('Restaurant dinner', 120.00, 4);
  var lunch = Expense.tip('Lunch', 25.00, 20);
  var gym = Expense.recurring('Gym membership', 45.00, 'monthly');

  print('${dinner.description}: \$${dinner.amount.toStringAsFixed(2)} - ${dinner.notes}');
  print('${lunch.description}: \$${lunch.amount.toStringAsFixed(2)} - ${lunch.notes}');
  print('${gym.description}: \$${gym.amount.toStringAsFixed(2)} - ${gym.notes}');
}

Exercise 3: Flexible User Class (Hard)

Create a User class for your expense app with:

  • Properties: name, email, currency, monthlyBudget, notifications
  • Main constructor with named parameters (all required except notifications default = true)
  • User.quick(name, email) - uses USD currency, $2000 budget
  • User.premium(name, email, monthlyBudget) - USD currency, notifications on

Solution:

class User {
  String name;
  String email;
  String currency;
  double monthlyBudget;
  bool notifications;

  User({
    required this.name,
    required this.email,
    required this.currency,
    required this.monthlyBudget,
    this.notifications = true,
  });

  User.quick(this.name, this.email)
    : currency = 'USD',
      monthlyBudget = 2000.0,
      notifications = true;

  User.premium(this.name, this.email, this.monthlyBudget)
    : currency = 'USD',
      notifications = true;

  void printProfile() {
    String notif = notifications ? '✅' : '❌';
    print('─────────────────');
    print('👤 $name');
    print('📧 $email');
    print('💵 Budget: $currency \$${monthlyBudget.toStringAsFixed(2)}/month');
    print('🔔 Notifications: $notif');
  }
}

void main() {
  var user1 = User.quick('John Doe', 'john@example.com');
  var user2 = User.premium('Jane Smith', 'jane@example.com', 3500.0);
  var user3 = User(
    name: 'Bob Wilson',
    email: 'bob@example.com',
    currency: 'EUR',
    monthlyBudget: 2500.0,
    notifications: false,
  );

  user1.printProfile();
  user2.printProfile();
  user3.printProfile();
}

Mistake 1: Forgetting Initializer List Colon

// ❌ Wrong
Expense.quick(this.description, this.amount, this.category) 
  date = DateTime.now();

// ✅ Correct - need the colon
Expense.quick(this.description, this.amount, this.category) 
  : date = DateTime.now();

Mistake 2: Mixing Positional and Named Parameters Incorrectly

// ❌ Wrong - can't mix freely
Expense(this.description, {required this.amount}, this.category);

// ✅ Correct - positional first, then named
Expense(this.description, this.category, {required this.amount});

Mistake 3: Not Using required for Named Parameters

// ❌ Wrong - amount could be null
Expense({this.description, this.amount, this.category});

// ✅ Correct - make required fields explicit
Expense({
  required this.description,
  required this.amount,
  required this.category,
});

Mistake 4: Forgetting this in Named Constructors

// ❌ Wrong
Expense.quick(description, amount, category)
  : date = DateTime.now();

// ✅ Correct
Expense.quick(this.description, this.amount, this.category)
  : date = DateTime.now();

Named constructors let you create objects in different ways

Initializer lists (:) set properties before object creation

Optional positional parameters use [] brackets

Named parameters use {} curly braces and are more readable

Default values make parameters optional with sensible defaults

required keyword makes named parameters mandatory

Combine techniques for maximum flexibility

1. What's the difference between a regular constructor and a named constructor?

Answer:

  • Regular constructor: Expense(...) - only one per class
  • Named constructor: Expense.quick(...) - can have multiple with different names, each providing different ways to create objects

2. What does the : (colon) mean in a constructor?

Answer:
The colon starts the initializer list, where you can set property values before the constructor body runs. It's used to initialize properties that aren't in the parameter list.

3. When should you use named parameters vs positional parameters?

Answer:

  • Positional: When order is obvious and there are few parameters (2-3)
  • Named: When you have many parameters, some are optional, or readability is important

In Lesson 4: Encapsulation, we'll learn:

  • How to make properties private (with _ underscore)
  • Why we should hide internal data
  • Getters and setters for controlled access
  • Validation to prevent invalid data
  • Keeping our expense data safe!

Example preview:

class Expense {
  String _description;  // Private!
  double _amount;       // Private!

  // Can't do: expense._amount = -100;
  // Must use: expense.setAmount(100);

  set amount(double value) {
    if (value < 0) {
      print('❌ Amount cannot be negative!');
      return;
    }
    _amount = value;
  }
}

See you in Lesson 4! 🚀

  • Try creating constructors for other classes: Category, PaymentMethod, Budget
  • Experiment with combining multiple techniques
  • Think about which constructor style makes your code most readable

Remember: The goal is to make object creation easy and intuitive for whoever uses your class (including future you)! 💪

Dart Object Oriented For Beginner : Expense Manager Case Study Part 2

Lesson 2: Creating Your First Class

Duration: 30 minutes

App Feature: 💰 Building the Expense Class

What You'll Build: Create an Expense class to represent a single expense

Prerequisites: Complete Lesson 1

By the end of this lesson, you'll be able to:

  • ✅ Write your first Dart class
  • ✅ Understand properties (instance variables)
  • ✅ Create objects from your class
  • ✅ Use constructors to initialize objects
  • ✅ Add methods to make objects do things
  • ✅ Work with multiple expense objects

Remember from Lesson 1:

  • A class is a blueprint/template
  • An object is an actual instance created from that class
  • Example: Expense class → your coffee purchase object

Today we're going to actually write this code ourselves!

Let's start with the simplest possible Expense class:

class Expense {
  // Properties (also called instance variables or fields)
  String description;
  double amount;
  String category;
  DateTime date;
}

Breaking It Down:

class Expense {
  • class keyword tells Dart we're creating a new class
  • Expense is the name (always start with capital letter!)
  • { opens the class body
  String description;
  double amount;
  String category;
  DateTime date;
  • These are properties - data that each expense will store
  • String = text (description, category)
  • double = decimal number (amount like 4.50)
  • DateTime = date and time
}
  • Closes the class body

🎯 Try It Yourself:

Create a file called expense.dart and type this class. Pay attention to:

  • Capital E in Expense
  • Semicolons ; after each property
  • Proper indentation (2 or 4 spaces)

Now that we have our class, let's create actual expense objects!

void main() {
  // Create an object using the class
  var coffee = Expense();

  // Set the properties
  coffee.description = 'Morning coffee';
  coffee.amount = 4.50;
  coffee.category = 'Food';
  coffee.date = DateTime.now();

  // Print the details
  print('I spent \$${coffee.amount} on ${coffee.description}');
}

Understanding the Code:

var coffee = Expense();
  • var = variable (Dart figures out the type)
  • coffee = variable name (our choice)
  • Expense() = calling the class to create a new object
  • The () is important - it creates a new instance
coffee.description = 'Morning coffee';
  • Use dot notation (.) to access properties
  • Set each property one by one
DateTime.now()
  • Gets the current date and time
  • Perfect for tracking when you made the expense

🎯 Try It Yourself:

Add this code below your class and run it. You should see:

I spent $4.50 on Morning coffee

Our code works, but there's a problem. Try running this:

void main() {
  var expense = Expense();
  print('Amount: ${expense.amount}');
}

What happens? You'll get an error!

Error: Non-nullable instance field 'amount' must be initialized.

This is because we created an expense but didn't set its properties. Dart doesn't know what values to use!

We need a better way to create objects...

A constructor is a special method that runs when you create an object. It initializes (sets up) the object with data.

Basic Constructor:

class Expense {
  String description;
  double amount;
  String category;
  DateTime date;

  // Constructor - same name as the class
  Expense(String desc, double amt, String cat, DateTime dt) {
    description = desc;
    amount = amt;
    category = cat;
    date = dt;
  }
}

void main() {
  // Now we MUST provide values when creating an object
  var coffee = Expense('Coffee', 4.50, 'Food', DateTime.now());
  print('${coffee.description}: \$${coffee.amount}');
}

Understanding Constructors:

Expense(String desc, double amt, String cat, DateTime dt) {
  • Constructor has the same name as the class
  • Takes parameters (the values we need)
  • No return type (not even void)
  description = desc;
  amount = amt;
  • Inside the constructor, we assign parameter values to properties
var coffee = Expense('Coffee', 4.50, 'Food', DateTime.now());
  • Now we pass values when creating the object
  • Order matters! (description, amount, category, date)

Dart has a shortcut that makes constructors much cleaner:

class Expense {
  String description;
  double amount;
  String category;
  DateTime date;

  // Shortcut constructor using 'this'
  Expense(this.description, this.amount, this.category, this.date);
}

This does the same thing as before, but in one line!

  • this.description means "set the description property to the value passed in"
  • Much cleaner and easier to read
  • This is the style most Dart developers use

🎯 Try It Yourself:

Update your Expense class to use the shortcut constructor and create 3 different expenses:

void main() {
  var coffee = Expense('Coffee', 4.50, 'Food', DateTime.now());
  var lunch = Expense('Lunch at cafe', 12.75, 'Food', DateTime.now());
  var netflix = Expense('Netflix subscription', 15.99, 'Entertainment', DateTime.now());

  print('${coffee.description}: \$${coffee.amount}');
  print('${lunch.description}: \$${lunch.amount}');
  print('${netflix.description}: \$${netflix.amount}');
}

So far our objects just hold data. Let's make them do something useful!

A method is a function inside a class that can work with the object's data.

class Expense {
  String description;
  double amount;
  String category;
  DateTime date;

  Expense(this.description, this.amount, this.category, this.date);

  // Method to print expense details
  void printDetails() {
    print('━━━━━━━━━━━━━━━━━━━━');
    print('📝 Description: $description');
    print('💵 Amount: \$$amount');
    print('📁 Category: $category');
    print('📅 Date: ${date.toString().split(' ')[0]}');
    print('━━━━━━━━━━━━━━━━━━━━');
  }
}

void main() {
  var coffee = Expense('Morning coffee', 4.50, 'Food', DateTime.now());

  // Call the method
  coffee.printDetails();
}

Understanding Methods:

void printDetails() {
  • void = doesn't return anything
  • printDetails = method name (use camelCase)
  • () = no parameters needed
print('💵 Amount: \$$amount');
  • Inside methods, we can directly access properties
  • No need for this.amount, just amount
  • \$ escapes the dollar sign so it prints literally
coffee.printDetails();
  • Call methods using dot notation
  • Don't forget the ()!

🎯 Try It Yourself:

Add the printDetails() method and create 3 expenses. Call printDetails() on each:

void main() {
  var coffee = Expense('Coffee', 4.50, 'Food', DateTime.now());
  var uber = Expense('Uber to work', 8.20, 'Transport', DateTime.now());
  var movie = Expense('Movie ticket', 12.00, 'Entertainment', DateTime.now());

  coffee.printDetails();
  uber.printDetails();
  movie.printDetails();
}

Methods can also calculate and return values:

class Expense {
  String description;
  double amount;
  String category;
  DateTime date;

  Expense(this.description, this.amount, this.category, this.date);

  void printDetails() {
    print('━━━━━━━━━━━━━━━━━━━━');
    print('📝 $description');
    print('💵 \$$amount');
    print('📁 $category');
    print('📅 ${date.toString().split(' ')[0]}');
    print('━━━━━━━━━━━━━━━━━━━━');
  }

  // Method that returns a boolean
  bool isMajorExpense() {
    return amount > 100;
  }

  // Method that returns a String
  String getSummary() {
    return '$description: \$$amount [$category]';
  }

  // Method that returns a formatted amount
  String getFormattedAmount() {
    return '\$${amount.toStringAsFixed(2)}';
  }
}

void main() {
  var laptop = Expense('New laptop', 899.99, 'Electronics', DateTime.now());
  var coffee = Expense('Coffee', 4.50, 'Food', DateTime.now());

  // Using methods that return values
  print(laptop.getSummary());
  print('Is major expense? ${laptop.isMajorExpense()}');
  print('Formatted: ${laptop.getFormattedAmount()}');

  print('');

  print(coffee.getSummary());
  print('Is major expense? ${coffee.isMajorExpense()}');
}

Output:

New laptop: $899.99 [Electronics]
Is major expense? true
Formatted: $899.99

Coffee: $4.50 [Food]
Is major expense? false

Understanding Return Values:

bool isMajorExpense() {
  return amount > 100;
}
  • bool = this method returns true or false
  • return sends the value back
  • Can use the returned value in conditions or print it
String getSummary() {
  return '$description: \$$amount [$category]';
}
  • String = returns text
  • Builds a nice formatted string
  • Return value can be stored in a variable or printed directly

Here's our complete Expense class with everything we've learned:

class Expense {
  // Properties
  String description;
  double amount;
  String category;
  DateTime date;

  // Constructor
  Expense(this.description, this.amount, this.category, this.date);

  // Method: Print detailed information
  void printDetails() {
    print('━━━━━━━━━━━━━━━━━━━━');
    print('📝 Description: $description');
    print('💵 Amount: ${getFormattedAmount()}');
    print('📁 Category: $category');
    print('📅 Date: ${getFormattedDate()}');
    if (isMajorExpense()) {
      print('⚠️  This is a major expense!');
    }
    print('━━━━━━━━━━━━━━━━━━━━');
  }

  // Method: Check if major expense
  bool isMajorExpense() {
    return amount > 100;
  }

  // Method: Get one-line summary
  String getSummary() {
    String emoji = isMajorExpense() ? '🔴' : '🟢';
    return '$emoji $description: ${getFormattedAmount()} [$category]';
  }

  // Method: Get formatted amount with 2 decimals
  String getFormattedAmount() {
    return '\$${amount.toStringAsFixed(2)}';
  }

  // Method: Get formatted date (without time)
  String getFormattedDate() {
    return date.toString().split(' ')[0];
  }
}

void main() {
  print('🏦 MY EXPENSES\n');

  // Create multiple expenses
  var expenses = [
    Expense('Monthly rent', 1200.00, 'Bills', DateTime.now()),
    Expense('Groceries', 67.50, 'Food', DateTime.now()),
    Expense('Coffee', 4.50, 'Food', DateTime.now()),
    Expense('New phone', 799.99, 'Electronics', DateTime.now()),
    Expense('Gas', 45.00, 'Transport', DateTime.now()),
  ];

  // Print summary for each
  print('SUMMARY:');
  for (var expense in expenses) {
    print(expense.getSummary());
  }

  print('\n');

  // Print details for major expenses
  print('MAJOR EXPENSES (>$100):');
  for (var expense in expenses) {
    if (expense.isMajorExpense()) {
      expense.printDetails();
      print('');
    }
  }

  // Calculate total
  double total = 0;
  for (var expense in expenses) {
    total += expense.amount;
  }
  print('💰 TOTAL SPENT: \$${total.toStringAsFixed(2)}');
}

Now it's your turn to practice! Complete these exercises to solidify your understanding:

Exercise 1: Basic Class Creation (Easy)

Create a Category class with:

  • Properties: name (String), icon (String), color (String)
  • Constructor that takes all three properties
  • Method: getLabel() that returns "icon name" (e.g., "🍔 Food")

Solution:

class Category {
  String name;
  String icon;
  String color;

  Category(this.name, this.icon, this.color);

  String getLabel() {
    return '$icon $name';
  }
}

void main() {
  var food = Category('Food', '🍔', 'green');
  var transport = Category('Transport', '🚗', 'blue');

  print(food.getLabel());
  print(transport.getLabel());
}

Exercise 2: Adding Methods (Medium)

Add these methods to your Expense class:

  1. isThisMonth() - returns true if expense is from current month
  2. isFood() - returns true if category is "Food"
  3. getDaysAgo() - returns how many days ago this expense was made

Hints:

  • Use DateTime.now() to get current date
  • Use date.difference(otherDate).inDays to calculate days
  • Use date.month and date.year to check if same month

Solution:

bool isThisMonth() {
  DateTime now = DateTime.now();
  return date.year == now.year && date.month == now.month;
}

bool isFood() {
  return category == 'Food';
}

int getDaysAgo() {
  DateTime now = DateTime.now();
  return now.difference(date).inDays;
}

Exercise 3: Real-World Scenario (Hard)

Create expenses for your last week and:

  1. Print all expenses from this month
  2. Calculate total food expenses
  3. Find the largest expense
  4. Count how many major expenses (>$100)

Challenge yourself before looking at the solution!

Solution:

void main() {
  var expenses = [
    Expense('Rent', 1200.00, 'Bills', DateTime(2025, 10, 1)),
    Expense('Lunch', 15.50, 'Food', DateTime(2025, 10, 5)),
    Expense('Coffee', 4.50, 'Food', DateTime(2025, 10, 6)),
    Expense('Groceries', 89.30, 'Food', DateTime(2025, 10, 7)),
    Expense('Uber', 12.00, 'Transport', DateTime(2025, 10, 8)),
  ];

  // 1. Print this month's expenses
  print('THIS MONTH\'S EXPENSES:');
  for (var expense in expenses) {
    if (expense.isThisMonth()) {
      print(expense.getSummary());
    }
  }

  // 2. Total food expenses
  double foodTotal = 0;
  for (var expense in expenses) {
    if (expense.category == 'Food') {
      foodTotal += expense.amount;
    }
  }
  print('\nTotal food: \${foodTotal.toStringAsFixed(2)}');

  // 3. Find largest expense
  Expense? largest;
  for (var expense in expenses) {
    if (largest == null || expense.amount > largest.amount) {
      largest = expense;
    }
  }
  print('Largest: ${largest?.getSummary()}');

  // 4. Count major expenses
  int majorCount = 0;
  for (var expense in expenses) {
    if (expense.isMajorExpense()) {
      majorCount++;
    }
  }
  print('Major expenses: $majorCount');
}

Mistake 1: Forgetting this in Constructor

// ❌ Wrong
Expense(description, amount, category, date);

// ✅ Correct
Expense(this.description, this.amount, this.category, this.date);

Mistake 2: Wrong Method Call

// ❌ Wrong - no parentheses
coffee.printDetails;

// ✅ Correct
coffee.printDetails();

Mistake 3: Using Class Name Instead of Object

// ❌ Wrong - Expense is the class, not an object
print(Expense.amount);

// ✅ Correct - coffee is the object
var coffee = Expense('Coffee', 4.50, 'Food', DateTime.now());
print(coffee.amount);

Mistake 4: Forgetting Return Statement

// ❌ Wrong - no return
String getSummary() {
  '$description: \$$amount';
}

// ✅ Correct
String getSummary() {
  return '$description: \$$amount';
}

Before moving to Lesson 3, make sure you understand:

Classes are blueprints - define structure with properties and methods

Objects are instances - created using the class

Constructors initialize objects - use this.property shortcut

Properties hold data - accessed with dot notation

Methods define behavior - can be void or return values

Use proper naming - classes PascalCase, methods camelCase

Test your understanding:

1. What's the difference between a property and a method?

Answer:

  • Property = data (like description, amount)
  • Method = behavior/action (like printDetails(), getSummary())

2. Why do we use constructors?

Answer:
To initialize objects with data when we create them, ensuring all required values are set.

3. What does this mean in a constructor?

Answer:
this refers to the current object being created. this.amount means "the amount property of this specific expense object".

In Lesson 3: Constructors Deep Dive, we'll learn:

  • Named constructors for easier object creation
  • Optional parameters
  • Default values
  • Factory constructors
  • Making our Expense class even more flexible!

Example preview:

// Instead of this:
var expense = Expense('Coffee', 4.50, 'Food', DateTime.now());

// We'll be able to do this:
var expense = Expense.quick('Coffee', 4.50, 'Food');
var bill = Expense.monthly('Rent', 1200.00);

Much cleaner, right? See you in Lesson 3! 🚀

Remember: Don't rush! Make sure you can complete the exercises before moving forward. Practice is key! 💪

Dart Object Oriented For Beginner : Expense Manager Case Study Part 1

Lesson 1: What is OOP? (Why We Need It)

Duration: 15 minutes

App Feature: 🎯 Planning our Expense Manager

What You'll Learn: Understand how OOP helps organize our expense tracking app

Welcome to your journey of learning Dart and Object-Oriented Programming! Instead of learning abstract concepts, we're going to build a real expense manager app together. By the end of this tutorial, you'll understand not just what OOP is, but why it's essential for building apps.

Imagine you want to track your expenses. Let's say you want to record:

  • A coffee you bought for $4.50
  • Groceries for $85.50
  • Netflix subscription for $15.99

Approach 1: Separate Variables (The Bad Way)

void main() {
  // First expense - Coffee
  String expense1Description = 'Coffee';
  double expense1Amount = 4.50;
  String expense1Category = 'Food';
  DateTime expense1Date = DateTime.now();

  // Second expense - Groceries
  String expense2Description = 'Groceries';
  double expense2Amount = 85.50;
  String expense2Category = 'Food';
  DateTime expense2Date = DateTime.now();

  // Third expense - Netflix
  String expense3Description = 'Netflix';
  double expense3Amount = 15.99;
  String expense3Category = 'Entertainment';
  DateTime expense3Date = DateTime.now();

  print('Expense 1: $expense1Description - \$$expense1Amount');
  print('Expense 2: $expense2Description - \$$expense2Amount');
  print('Expense 3: $expense3Description - \$$expense3Amount');
}

Problems with This Approach:

  1. Messy and repetitive - We need 4 variables for each expense!
  2. Hard to manage - What if you have 50 expenses? That's 200 variables!
  3. No relationship - Nothing connects expense1Description with expense1Amount
  4. Error-prone - Easy to mix up expense1Amount with expense2Amount
  5. Can't reuse code - Want to calculate total? You need to add each variable manually

Try to imagine tracking 10 expenses this way... That's 40 separate variables! 😱

OOP lets us bundle related data together. Instead of 4 separate variables per expense, we create a blueprint (called a class) and make objects from it.

Think of it Like This:

Real World Analogy:

🏠 House Blueprint (Class)

  • A blueprint shows what every house should have: rooms, doors, windows
  • It's not an actual house, just a template

🏡 Actual Houses (Objects)

  • You can build many houses from one blueprint
  • Each house is unique (different colors, sizes) but follows the blueprint

In Programming:

📋 Expense Class (Blueprint)

  • Defines what every expense should have: description, amount, category, date
  • Just a template, not actual data

💰 Expense Objects (Actual Expenses)

  • Coffee expense: $4.50, Food, Today
  • Netflix expense: $15.99, Entertainment, Today
  • Each is a real expense created from the template

What is a Class?

A class is a blueprint or template that defines:

  • Properties (data): what information it stores
  • Methods (actions): what it can do

Think of it as a cookie cutter - it shapes what the cookies will look like, but it's not the cookie itself.

What is an Object?

An object is an actual instance created from a class.

Think of it as the cookies - real things you can eat, made from the cookie cutter template.

Don't worry if you don't understand everything yet - we'll learn step by step. This is just to show you the difference:

// The BLUEPRINT - This is a class
class Expense {
  String description;
  double amount;
  String category;
  DateTime date;
}

void main() {
  // Creating OBJECTS from the blueprint
  var coffee = Expense();
  coffee.description = 'Coffee';
  coffee.amount = 4.50;
  coffee.category = 'Food';
  coffee.date = DateTime.now();

  var netflix = Expense();
  netflix.description = 'Netflix';
  netflix.amount = 15.99;
  netflix.category = 'Entertainment';
  netflix.date = DateTime.now();

  print('${coffee.description}: \$${coffee.amount}');
  print('${netflix.description}: \$${netflix.amount}');
}

See the difference?

  • We defined the Expense structure once
  • We created multiple expenses easily
  • Each expense is a separate object with its own data
  • The code is cleaner and more organized

As we build our expense manager app, you'll see how OOP helps us:

1. Organization

Without OOP: 100 expenses = 400+ variables floating around
With OOP: 100 expense objects, each neatly packaged

2. Reusability

// Want to add a new expense? Just create an object!
var lunch = Expense();
var dinner = Expense();
var gas = Expense();
// Same blueprint, different data

3. Maintainability

// Need to add a "notes" field to all expenses?
// Change the class ONCE, all objects get the new feature
class Expense {
  String description;
  double amount;
  String category;
  DateTime date;
  String notes; // Added here - affects all expenses!
}

4. Real-World Modeling

Your app will have:
- Expense objects (each purchase)
- Category objects (Food, Transport, etc.)
- Budget objects (monthly limits)
- User object (your profile)

Each is a separate class, working together!

As we build our expense manager, we'll learn these four core concepts:

1. Encapsulation 🔒

Bundle data and methods together, hide internal details.

In our app: Keep expense data safe, validate amounts (can't be negative!)

2. Inheritance 🌳

Create new classes based on existing ones.

In our app: RecurringExpense (like Netflix) inherits from Expense but adds frequency

3. Polymorphism 🎭

One action, multiple forms.

In our app: All expenses can printDetails(), but recurring ones show frequency too

4. Abstraction 🎯

Hide complex details, show only what's necessary.

In our app: You don't need to know HOW expenses are stored, just add/view/delete them

Don't worry if these seem confusing now! We'll learn each one by actually using it in our app.

Over the next lessons, we'll build a complete expense tracking system:

📱 Expense Manager App
├── 💰 Expense Class
│   ├── Track amount, date, category
│   ├── Validate data (no negative amounts!)
│   └── Calculate totals
│
├── 🔄 RecurringExpense Class
│   ├── Monthly bills (rent, subscriptions)
│   └── Calculate yearly costs
│
├── 🎯 OneTimeExpense Class
│   ├── Special purchases (gifts, emergencies)
│   └── Tag occasions
│
├── 💳 PaymentMethod Classes
│   ├── Credit card, cash, digital wallet
│   └── Process payments differently
│
└── 📊 ExpenseManager Class
    ├── Store all expenses
    ├── Filter by category
    ├── Calculate totals
    └── Generate reports

Before moving to the next lesson, make sure you can answer these:

✅ Self-Check Questions:

  1. What's the difference between a class and an object? Click to see answer
  • Class = Blueprint/template (defines structure)
  • Object = Actual instance (real data)
  • Example: Expense is the class, your coffee purchase is an object
  1. Why is OOP better than using separate variables? Click to see answer
  • Organizes related data together
  • Easier to manage many items
  • Less error-prone
  • Code is reusable
  1. Name one real-world example of a class and its objects Click to see answer

Examples:

  • Class: Car → Objects: Your Toyota, Your friend's Honda
  • Class: Student → Objects: John, Sarah, Mike
  • Class: Song → Objects: "Bohemian Rhapsody", "Hotel California"

Before moving to Lesson 2, think about what properties an Expense should have:

Your Task:

Write down (on paper or in notes) what information you'd want to track for each expense:

Example answers:

  • ✓ Description (what you bought)
  • ✓ Amount (how much it cost)
  • ✓ Category (Food, Transport, etc.)
  • ✓ Date (when you bought it)
  • ? What else would be useful?

Bonus questions to think about:

  • Should expenses have a unique ID number?
  • Should we track the payment method (cash, card)?
  • Should we allow notes or tags?

We'll use your ideas in the next lesson when we actually create the Expense class!

Before moving forward, remember:

OOP organizes code into objects - like real-world things

Classes are blueprints - they define structure

Objects are instances - actual data created from classes

OOP makes code cleaner - easier to read and maintain

Perfect for apps - Flutter itself is built on OOP principles

In Lesson 2, we'll:

  • Write our first Expense class
  • Create actual expense objects
  • Learn about constructors
  • Add methods to print expense details
  • See our code actually work!

Time to get hands-on and write real code! 🚀

Common questions beginners ask:

Q: Do I need to memorize all the OOP terms?

A: No! Focus on understanding the concepts. The terms will become natural as you use them.

Q: Is OOP hard?

A: It might feel strange at first, but by building a real app, you'll see why it's actually easier than the alternative!

Q: Can I skip OOP and just learn Flutter?

A: Flutter IS built with OOP! Every widget is a class. Understanding OOP will make Flutter much easier.

Q: What if I get stuck?

A: That's normal! Re-read sections, try the examples, and remember - we're building this step by step together.

Ready for Lesson 2? Let's write some code! →

Beyond Cost: Lessons from our Migration to Hetzner

When engineering teams discuss infrastructure migration, the conversation often starts and often terminates with cost reduction. However, a significant architectural decision requires a synthesis of financial prudence, regulatory adherence, and operational excellence. The transition of our Kubernetes staging environment from DigitalOcean to Hetzner was not merely a cloud hop, it was a deliberate, strategic refactoring of our entire infrastructure foundation, driven by mounting technical debt and the non-negotiable demands of PCI-DSS compliance.

The Tipping Point: Trading Simplicity for Control

In the early stages of our startup lifecycle, DigitalOcean’s simplicity and user-friendly control panel were highly effective for rapid prototyping and initial speed. This high-abstraction environment was invaluable. As our fintech product lines expanded, the staging environment grew commensurately, needing to precisely mirror production to enable rigorous testing of complex financial features, such as payment flows and third-party integrations. This demand for high-fidelity staging quickly pushed us against a wall of unsustainable costs.

The staging environment alone escalated to a consumption rate of $1,200 monthly on DigitalOcean. While the pricing was transparent, the underlying rigid model capped our ability to experiment affordably at scale. This moment represented a pivotal shift: the company was moving past the initial growth phase, necessitating the exchange of abstraction convenience for the long-term benefits of high-control, raw performance, and a lower cost-per-unit infrastructure. The core objective became leveraging infrastructure optimization as a financial catalyst for sustained growth, much like scaling companies utilize elasticity to fund expansion.

Defining Success: The Three Pillars of the Migration

To ensure this complex migration served the long-term strategic needs of the organization, we defined three non-negotiable success metrics. First, Cost Efficiency: achieve substantial, verifiable savings without sacrificing production-grade reliability or performance. Second, PCI-DSS Compliance: refactor the network architecture to meet stringent regulatory isolation requirements explicitly demanded of a modern fintech operation. Third, Developer Velocity: use the infrastructure shift as a mandate to modernize Continuous Delivery, enhancing security while simultaneously accelerating deployment speed. Achieving these three goals simultaneously demanded a fundamentally different infrastructure philosophy.

The technical execution of the migration centered on acquiring superior control over two core functions: cost management and network topology. The choice of Hetzner was validated through rigorous benchmarking, confirming that the cost savings were paired with sufficient technical capability to satisfy stringent compliance demands.

Quantifying Savings and Benchmarking Performance

The financial catalyst for the move was profound. The previous monthly expenditure of $1,200 for our staging workload on DigitalOcean was reduced to approximately €224, translating to roughly $260 on Hetzner. This achieved a near 80% reduction in monthly infrastructure costs for the non-production environment.

To quantify these savings rigorously, we leveraged infrastructure-as-code principles. Terraform was used to simulate and estimate costs across potential architectures on Hetzner Cloud, specifically benchmarking the CX-series servers against DigitalOcean’s droplets.

This process confirmed that Hetzner delivered equivalent or superior compute density and raw performance-per-dollar, eliminating the concern that cost efficiency would lead to performance trade-offs. This monthly saving, approximately €940, could then be redirected toward core business activities, such as hiring and feature development, turning infrastructure optimization into a powerful lever for the business.

The table below summarizes the technical trade-offs and strategic impacts of moving from a high-abstraction platform to an environment offering bare-metal control and cost-efficiency.

Table 1: Infrastructure and Compliance Comparison: DigitalOcean versus Hetzner

Feature DigitalOcean(previous state) Hetzner(current state) Strategic Impact
Monthly Cost $1200 €224($260) 80% Cost Reduction
Networking Model High-Abstraction VPC Bare-Metal Private Network, VLAN-level control Enable strict PCI-DSS segmentation
Environment Isolation Public IPs, citing risk Zero-Trust, VPN-Only Access Secured environment per PCI-DSS Requirement 6.4
Compute Density Standard Virtualized Droplets Dedicated Cores, CX Series Improved Performance-per-Dollar

Compliance as the Primary Design Constraint, PCI-DSS 6.4

In regulated industries like fintech, staging environments must be treated with production-grade discipline because compliance failures frequently originate in non-production settings. PCI-DSS Requirement 6.4 strictly mandates explicit logical or physical separation between preproduction, development, and production environments.

Under DigitalOcean, achieving strict segmentation proved operationally challenging. The platform’s high-level networking abstractions and the automatic assignment of public IP addresses, even within VPCs, made auditable network segmentation clunky.

Although DigitalOcean offers VPCs for private network interfaces, the abstracted nature of the service often lacked the granularity required to satisfy auditors focused on layer 2 and layer 3 control. This configuration frequently resulted in compliance flags regarding insufficient segmentation, despite the use of mock cardholder data.

The migration to Hetzner solved this regulatory challenge by offering a closer equivalent to bare-metal network primitives. Hetzner's private networking functionality allowed the engineering team to construct robust, auditable VLAN-like isolation. This shift provided the granular L2, L3 control necessary to restrict access to staging clusters entirely: ingress and egress access were strictly limited to connections originating from the corporate WireGuard VPN. This enforcement of a Zero-Trust architecture at the network perimeter, paired with manual configuration of robust audit logs and access controls, ensured complete traceability, thus satisfying granular PCI-DSS requirements for non-production environments. The architectural choice of Hetzner, prioritizing lower-level network control, was entirely dictated by the regulatory requirement for infrastructure primitives that enable audit-ready segmentation.

Enhanced Security and Granular Network Control

The move to Hetzner established a truly secure sandbox for developers. Previously, developers testing APIs and microservices risked accidental exposure to the public internet, potentially leading to data leaks or exposure to DDoS threats. The architectural pivot to Hetzner’s private network facilitated the full implementation of a Zero Trust model: staging clusters are now completely isolated, with traffic routed exclusively via the WireGuard VPN. This VPN is integrated with the Single Sign-On, using role-based keys to ensure only authorized engineers can access the staging environment, effectively prioritizing security early in the deployment process.

This capability to enforce deep segmentation underscores a critical difference: while DigitalOcean’s user-friendly networking provides abstraction, it lacks the necessary granularity needed for specialized regulatory compliance environments, particularly compared to Hetzner's offering, which allows for segmentation closer to a physical bare-metal setup. This granular control was paramount to achieving the necessary compliance posture.

The strategic infrastructure move created the perfect opportunity to address compounding issues within the Continuous Delivery (CD) pipeline, where security liabilities had begun to directly impact auditability and velocity.

The DevSecOps Nightmare of Imperative CI/CD

Our previous CD pipeline, reliant entirely on GitHub Actions within the DigitalOcean ecosystem, was an architectural liability masquerading as a convenience. Kubernetes configurations, including sensitive kubeconfigs and application manifests, were often baked directly into the workflow files.

This configuration created an inherent security flaw: sensitive data, even when obfuscated using base64 encoding, meant that a single repository breach or slipped secret could grant unauthorized access to cluster keys, constituting a blatant violation of the principle of least privilege. Furthermore, the entire system was imperative and scattered, making change management and security auditing extremely difficult. Auditing changes felt like chasing ghosts, a serious compliance vulnerability in a PCI-DSS environment where traceability is non-negotiable.

Embracing Declarative State with ArgoCD

The migration served as the mandate needed to adopt full GitOps principles using ArgoCD. The team transitioned from an imperative system, where scripts executed commands, to a declarative flow, where the Git repository serves as the single source of truth for the desired state.

This declarative approach immediately yielded massive security and auditability benefits. GitOps ensures that the Git commit history provides a natural, immutable audit log of every application configuration change, satisfying the rigorous traceability demands of PCI-DSS auditors. By pairing ArgoCD with tools like HashiCorp Vault, secrets are kept locked away, never exposed within CI logs, reinforcing the principle of least privilege.

We leveraged Helm charts extensively, making applications versioned, parameterized, and significantly easier to manage across multiple non-production environments. This professionalization of configuration management fundamentally eliminated configuration drift, improving reliability across all testing environments.

Table 2 details this necessary security and operational shift.
Table 2: DevOps Maturity Shift: From Imperative CI to Declarative GitOps

Pipeline Aspect Github Actions(Imperative) ArgoCD/GitOps(Declarative) Engineering Outcome
Configuration Management Kubeconfigs/Manifests baked into workflows Helm Charts, Git is Single Source of Truth Enhanced security, secrets isolation
Audit Trail Scattered CI/CD Logs, Manual Checks Immutable Git History and ArgoCD Events Instantaneous, tamper-proof auditability
Deployment Velocity Slow, Sequential Checks 50% Faster, Automated Sync Increased DevX and iteration speed
Compliance Risk, Drift High Risk of Configuration Drift Near Zero Drift Risk Ensures consistency between Git and Cluster State

The Measurable Velocity Payoff

The causal relationship between security constraints and velocity improvement is clearly demonstrated here. The need for auditability and least privilege, driven by regulatory compliance, forced the adoption of GitOps, which proved to be a superior operational methodology.

This transformation delivered immediate, quantifiable results: deployment times were halved, representing a 50% reduction in cycle time. The declarative consistency vastly improved reliability. Developers now operate with increased confidence, testing in a secure, production-mirrored sandbox without fear of external exposure. Furthermore, the ArgoCD UI provides a centralized dashboard for monitoring application sync status, offering developers self-service monitoring capabilities that reduce operational reliance on the core infrastructure team. The adoption of sophisticated deployment strategies, such as canary releases for critical updates, became reliable and routine.

A complex migration of this nature inevitably introduces friction. A high-caliber engineering story acknowledges these difficulties, as they highlight the resilience and ingenuity of the team involved. Our lean team faced three major hurdles that tested our migration limits, demonstrating the hidden operational cost inherent in shifting to a higher-control, lower-cost environment like Hetzner.

Refactoring Imperative Logic into Declarative Helm

The greatest initial challenge was the sheer volume of manual effort required to transition the legacy, imperative logic embedded within GitHub Actions into robust, reusable Helm charts. This involved meticulously extracting encoded environment variables and translating step-by-step CI/CD pipeline logic into standardized, parameterized values.yaml files.

Compounding this task was the steep learning curve associated with ArgoCD itself. The team faced significant difficulty debugging application synchronization issues, particularly those caused by Custom Resource Definition, CRD, mismatches or complex network configurations interacting unexpectedly with the new cluster architecture. Successfully managing this architectural shift required significant dedication to pair-programming and meticulous documentation.

Data Integrity During Persistent Volume Migration

Migrating persistent data, particularly sensitive application data, required careful planning to ensure integrity and minimize downtime. DigitalOcean provides a seamless block storage abstraction, making volume management largely transparent. Moving to Hetzner’s storage backend, which requires a greater degree of manual provisioning and control, necessitated a robust, verified migration process.

The team elected to use rsync over SSH tunnels for data transfer to Hetzner’s storage. This choice was deliberate: rsync ensures data integrity verification and is highly efficient for differential transfers. It achieves this by utilizing client/server hashing to compare files and only transferring the differences, significantly minimizing the amount of data sent over the network pipe. Despite the technical soundness of the approach, the manual nature of coordinating data movement across different cloud storage primitives demanded intense focus and robust integrity checks upon completion.

Team Resilience and Shared Ownership

This complex refactoring was executed by a lean team of four engineers, demanding ruthless focus on three core operational principles: audit, automate, and iterate. The scope of the work, encompassing cost modeling, PCI-DSS network redesign, Kubernetes cluster provisioning, GitOps implementation, and data migration, risked creating significant burnout and knowledge silos.

The countermeasure to this constraint was a cultural commitment to shared ownership. The team enforced mandatory pair-programming sessions for complex refactoring tasks and meticulously logged every configuration, debugging session, and architectural decision into a shared Git repository. This commitment ensured that organizational knowledge was distributed and collective ownership mitigated the intensity of the implementation friction.

This infrastructure transformation validates that constraints, especially regulatory ones, can serve as powerful accelerants for strategic modernization.

The True Return on Investment, ROI

Defining the success of this project requires moving beyond a simple financial metric. While the infrastructural savings, roughly €940 monthly, are materially significant, the true ROI calculation must be holistic, measuring strategic gains against initial effort.

The critical value metrics achieved include Reduced Risk, secured through an audit-ready compliance posture owing to true network segmentation and verifiable GitOps history. This is coupled with Increased Velocity, defined by 50% faster, more reliable deployments powered by a declarative CD model. Finally, the project fostered a positive Cultural Shift, leading to enhanced developer confidence and satisfaction, DevX, by providing a safe, production-mirrored sandbox.

Five Foundational Lessons for High-Growth Teams

The experience yielded critical, transferable lessons for engineering leaders navigating scale, regulation, and architectural debt:

  1. Staging Is Not an Afterthought, It Is a Security Mandate: In regulated sectors, security vulnerabilities often begin in non-production environments. Treat staging with the same discipline, security, and audit rigor applied to production systems, viewing it as a critical component of the Cardholder Data Environment, CDE.

  2. ROI Goes Beyond the Invoice: Financial savings are a welcome catalyst, but success must be measured by the long-term security posture, velocity gains, and cultural agility the migration unlocks.

  3. Constraint Drives Innovation: Regulatory requirements, such as PCI-DSS, should not be viewed solely as burdens. In this case, the need for auditable segmentation and least privilege forced the adoption of superior technologies, GitOps and Zero Trust networking, accelerating modernization across the board.

  4. Compliance and Velocity Can Coexist: Strategic tooling, ArgoCD and Helm, combined with strict architectural control, VPN-based access and detailed audit logging, allows teams to satisfy auditors while simultaneously empowering developers to move faster and with greater confidence.

  5. Staging Is Your Innovation Engine: A robust, secure, and cost-effective staging environment sets the pace for safe, fast iteration and experimentation. Infrastructure that encourages this behavior should be treated as a strategic asset, not merely a cost center.

The migration from DigitalOcean to Hetzner was far more than optimizing a billing statement. It was a deliberate choice to sharpen our compliance edge, accelerate development cycles, and establish a framework for scaling smarter. By acquiring the network control and cost-efficiency required for robust regulatory adherence, the team successfully turned a compliance constraint into an architectural advantage.

For technical leaders, the enduring lesson is clear: infrastructure decisions fundamentally shape a team’s culture, determine the company’s agility, and define its capacity to meet future regulatory and market demands head-on. We successfully shifted from consuming an abstracted cloud service to mastering the underlying primitives, a foundational step toward becoming a mature, enterprise-grade fintech operation.

How do you balance compliance and velocity in your infrastructure decisions? I’d love to hear how other teams are turning constraints into advantages

My Second PR: How I Bounced Back and Contributed to Scikit-learn

Steven here again.
Where to start... It was a busy busy week. Yes I know, I used the word 'busy' twice. Last week, I found an amazing project, BEHAFIOR-1K and it took me hours to understand the code that is related to the issue. Therefore, I wanted to find a bit of easy-going issue to contribute on. As I mentioned before, I am always interested in Machine Learning so I browsed through pandas, numpy and scikit-learn repositories. They are the three famous libraries that is used by Machin Learning projects. I thought it would be a good chance to leave some trace on this big size project.

Finding a "Good First Issue" in Scikit-learn
After the tough first experience, I knew I needed a different approach. Since I’ve always been interested in ML, I decided to choose the Scikit-learn repository. I figured, why not try to contribute to a tool I actually use? I went directly to their Issues tab on GitHub and started looking for labels like good first issue or help wanted. It felt way more focused, and that’s when I found it.

The issue
The issue was quite simple: change relative import paths to absolute import paths in some of their Cython files.

from ...utils._typedefs cimport ...
from sklearn.utils._typedefs cimport ...

The code change itself was just changing relative path to absolute path. Even though it was simple task, I had to go through project files to find the functions or types to make sure I wrote the correct absolute path. It may seem simple but I learned more interesting new technique through this procedure.

Cython???
Okay, so the task was just changing an import path. Simple, right? But I did learn some new technique that can be useful in future.
The files I was editing weren't standard .py files; they were .pyx and .pxd files. This was my first real encounter with Cython, which is a programming language used to give Python C-level speed. It’s one of the secret sauces that makes libraries like Scikit-learn so fast.

from ...utils._typedefs cimport float64_t, float32_t, intp_t

At first, I had no clear idea what cimport or float64_t meant. I learned that cimport is a special Cython command to import C-level definitions. And things like float64_t are basically C-style "nicknames" for NumPy data types.
By using these C-style types, Cython knows to treat them as simple, super-fast C variables instead of slower Python objects. So, while I was just fixing a file path, I accidentally learned a fundamental concept about how Python libraries are optimized for performance.

I don't know if you can get this feeling from my blog posts but I am having lots of fun doing this. I hope everyone else is experiencing the same.

Understanding the Modern Web Stack: WebAssembly(WASM), Web Workers, and the V8 Engine

Modern web applications are no longer just static pages. Today’s web apps need speed, concurrency, and the ability to run complex code efficiently in the browser. Key technologies that enable this are:

WebAssembly (Wasm) – Runs near-native performance code in browsers.

Web Workers – Allow background threads to run heavy tasks without freezing the UI.

V8 Engine – The JavaScript engine powering Chrome and Node.js, enabling JIT compilation and high performance.
1. WebAssembly (Wasm)

What is Wasm?

  • A binary instruction format for the web.

  • Designed for high-performance execution, almost like running native code.

  • Typically compiled from languages like C, C++, or Rust.

Why Wasm?

  • JavaScript alone can be slow for CPU-intensive tasks.

  • Wasm enables heavy computations, games, image/video processing, and scientific simulations to run efficiently in the browser.

How it works

  • Write code in a language like C/C++/Rust.

  • Compile it to a .wasm file.

  • Load it in JavaScript using the WebAssembly API.

  • Execute functions from JS, optionally interacting with the DOM.

2. Web Workers

What are Web Workers?

  • A browser feature that allows JavaScript code to run in a separate thread.

  • Prevents UI from freezing when performing heavy computations.

Types of Web Workers

  • Dedicated Workers – For a single script.

  • Shared Workers – Can be shared across multiple scripts/tabs.

  • Service Workers – Intercept network requests and enable offline capabilities.

How Web Workers help Wasm

  • Wasm modules can be run inside a Web Worker, so computationally heavy tasks don’t block the main thread.

Example: Running video encoding or AI inference in the background.

3. V8 Engine

What is V8?

  • The JavaScript engine developed by Google for Chrome and Node.js.

  • Compiles JS to machine code using JIT (Just-In-Time) compilation, giving near-native performance.

Role in WebAssembly

  • V8 also supports Wasm execution.

  • Converts .wasm bytecode to machine code and optimizes execution.

  • Works seamlessly with JS, allowing JS↔Wasm interop
    .

4. How They Work Together

Code Preparation:

Write computational code in C++/Rust → Compile to Wasm.

Loading Wasm in Browser:

JS fetches the .wasm file.

V8 engine compiles Wasm to machine code.

Offloading Heavy Tasks:

Use Web Workers to run Wasm modules in the background.

Main UI thread remains responsive.

Interop:

JS can call Wasm functions and vice versa.

Shared memory (via SharedArrayBuffer) allows fast communication between JS and Wasm in workers.

5. Real-World Use Cases

  • Gaming in the Browser: Unity or Unreal Engine exporting to WebAssembly.
  • Video & Image Processing: FFMPEG compiled to Wasm for in-browser transcoding.
  • Machine Learning: TensorFlow.js or ONNX running models with Wasm backend.
  • Cryptography & Compression: Running CPU-heavy tasks in the browser safely.

  1. Conclusion

The modern web stack is evolving to bring near-native performance to browsers.

  • WebAssembly handles heavy computation.
  • Web Workers ensure non-blocking, concurrent execution.
  • V8 Engine powers both JS and Wasm efficiently.

Together, they allow developers to build fast, responsive, and complex web applications, blurring the line between native and web apps.


The Challenges that Face Drones in Smart City Environments

The use of drones in logistical operations across urban environments has increased worldwide as more companies use them for delivering small packages.

The post The Challenges that Face Drones in Smart City Environments appeared first on EE Times.

Five Innovative Practices for Capacitors in the Era of Third-Generation Semiconductors

This article delves into the critical innovation race in passive components, particularly capacitors, driven by the widespread adoption of third-generation semiconductors (SiC & GaN). As these power devices operate at higher frequencies, temperatures, and power densities, traditional capacitors face severe challenges in size, reliability, and performance. Through five collaborative case studies with industry leaders like Infineon and onsemi, Yongming Electronics demonstrates how systemic innovation in materials and structure is providing the matching, reliable capacitor solutions essential for enabling next-generation power electronics in AI servers, EVs, and more.

The post Five Innovative Practices for Capacitors in the Era of Third-Generation Semiconductors  appeared first on EE Times.


Discord now says 70,000 government IDs may have leaked in provider hack

Over the weekend, Discord revealed that its users may have had their data compromised when a third-party service provider was hacked. At the time, the platform said that a "small number" of government IDs may have been illicitly accessed. Today, however, claims circulated that the attackers had obtained more than 2 million photos that had been used for age-verification purposes. In response, the company said that about 70,000 users "may have had government-ID photos exposed." Other user data that could have been compromised includes the users’ "name, Discord username, email and other contact details if provided to Discord customer support," as well as a limited amount of billing information. 

Engadget reached out to Discord for comment, but did not receive a response. However, Discord spokesperson Nu Wexler shared a statement about the issue with The Verge and said that some of the figures being shared were "inaccurate" and came from the attackers.

"The numbers being shared are incorrect and part of an attempt to extort a payment from Discord," Wexler said. "We will not reward those responsible for their illegal actions. All affected users globally have been contacted and we continue to work closely with law enforcement, data protection authorities, and external security experts. We’ve secured the affected systems and ended work with the compromised vendor."

This article originally appeared on Engadget at https://www.engadget.com/discord-now-says-70000-government-ids-may-have-leaked-in-provider-hack-225753321.html?src=rss

New York City is suing Meta, Snap, TikTok and YouTube over 'youth mental health crisis'

New York City, its school district and healthcare system have filed a lawsuit against Meta, Snap TikTok and YouTube for allegedly contributing to a "youth mental health crisis" with intentionally addictive platforms. The lawsuit is the latest in a long string of legal actions against social media platforms over their handling of safety and other issues facing teens. 

The city of New York was joined in the lawsuit by the city's school district and NYC Health + Hospitals, the city's largest public hospital system. The lawsuit alleges that the social media companies have intentionally designed their platforms to be addictive to children and that they have failed to implement effective safeguards. 

The companies, the suit claims "have created, caused and contributed to the youth mental health crisis in New York City, causing damage to the public’s health and safety, interfering with the use of public places, including schools, and endangering or injuring the health, safety, comfort or welfare of a considerable number of persons, including youth." It says the city, school district and hospitals have been forced "to devote significant resources—in terms of funding, employees, and time" to address the "youth mental health crisis" caused by the companies.

The lawsuit also specifically calls out the rise of viral posts about "subway surfing" in New York, noting that several teenagers have died attempting the stunt and more than 100 have been arrested. "Significantly, NYPD investigations have determined that the primary motivation of subway surfers is to imitate the subway surfing videos they see on social media, and to collect social media 'likes,'" the lawsuit says. It also claims that teachers and other school staff "experience secondary trauma and burnout associated with responding to students in crisis" due to social media.

Meta, Snap and TikTok didn't immediately respond to a request for comment on the lawsuit. In a statement, Google spokesperson José Castañeda said that "the allegations are simply not true" and "fundamentally misunderstand" YouTube. "YouTube is a streaming service where people come to watch everything from live sports, to podcasts to their favorite creators, primarily on TV screens, not a social network where people go to catch up with friends," he said. "We've also developed dedicated tools like Supervised Experiences for young people, guided by child safety experts, that give families control."

This article originally appeared on Engadget at https://www.engadget.com/big-tech/new-york-city-is-suing-meta-snap-tiktok-and-youtube-over-youth-mental-health-crisis-223916712.html?src=rss

Amazon Prime Day tech deals under $25: Save on Blink, Anker, Roku and Fire TV

Amazon's third (!) and final Prime-related sale of 2025 has reached its last few hours. But the October Prime Day sale still has plenty of nifty accessories, gadgets and tech that can be had for less than $25. You might not think many electronics could be worth your time for so cheap, but turns out there are some worthy contenders. We found deals on Bluetooth trackers, mini speakers, portable chargers, cables, streaming sticks and more — all pulled from Engadget's own testing for our guides and reviews. Most deals will likely end when the sale does, so shop these under $25 Prime Day tech deals while you can.  

Blink Mini 2 security camera for $20 ($20 off): This is the top budget pick in our guide to the best security cameras. The Mini 2 is a great option for indoor monitoring or you can put it outside with a weatherproof adapter, but since it needs to be plugged in, we like it for keeping an eye on your pets while you're away and watching over entry ways from the inside.

Audible (three months) for $3 ($42 off): From now through mid-December, you can get Amazon’s audiobook subscription for just a dollar a month for three months. Note that it will auto-renew at $15 per month after that, but you can cancel at any point.

Amazon Smart Plug for $13 ($12 off): We named this the best smart plug for Alexa users because it hooks up painlessly and stays connected reliably. Use it to control lamps or your holiday lights using programs and schedules in the Alexa app, or just your voice by talking to your Echo Dot or other Alexa-enabled listener.

Kasa TP-Link Smart Wi-FI outdoor plug for $15 ($7 off with Prime): We tested a similar plug for our buying guide to smart plugs and named it the best outdoor pick for HomeKit users — but this model only works with Alexa and the Google Assistant. The range was decent and setup was easy, like most TP-Link plugs. Grab this now and have automatic control of your holiday lights.

Anker Soundcore Select 4 Go speaker for $23 ($12 off with Prime): This is one of our top picks for a Bluetooth speaker. It gets pretty loud for its size and has decent sound quality. You can pair two together for stereo sound as well, and its IP67-rated design will keep it protected against water and dust.

Belkin Apple AirTag holder for $15 ($5 off with Prime): The best thing about Apple’s AirTags are their ability to rope in most any nearby iPhone to anonymously hunt for lost trackers. The worst thing is probably the tiny, slippery disk shape that can’t attach to anything without some help. This is the solution we suggest in our iPhone accessories guide.

Apple AirTag for $20 ($9 off): Here’s our pick for a Bluetooth tracker for iPhone users. These little discs have the most accurate finding ability of any fob we tested, thanks to Apple’s vast Find My network that taps into all nearby iPhones to track down your missing stuff. They could be louder and a hole would be nice, but nothing beats its accuracy.

Anker Nano portable charger for $20 ($10 off with Prime): It looks like an oldey timey lipstick case and can deliver a partial refill to any small device with a USB-C port. We named it a good pick after testing it for our battery guide.

Samsung Galaxy SmartTag2 for $20 ($10 off): Our favorite tracker for Samsung users is one of the best-looking fobs we tried. It’s got a wide finding network, drawing on nearby Samsung phones to ping your lost items (though not as large as Google or Apple’s networks). The deal isn’t an all-time low; it went as low as $15 back in July and only the white model is down to $20 right now.

Roku Streaming Stick Plus 2025 for $24 ($16 off): This is our top pick for the best streaming device for accessing free and live content. The dongle supports 4K video and HDR and doesn’t need to be plugged into the wall for power. It’s a great way to access any streaming service you could ask for: Netflix, Prime Video, Disney+, HBO Max and many more.

Anker USB-C to USB-C cable (10FT, 100W) for $9 ($3 off with Prime): Having a bad cable is almost as bad as not having a cable at all. We’re big fans of Anker’s cords. This one is a generous 10 feet and can deliver up to 100W of power. While it can transfer data, it does so slowly, so don’t grab this one for that purpose. This is $1 more than it sold for as a Prime-exclusive in July.

Anker Right-Angle USB-C braided charging cable (two-pack) for $9 ($7 off with Prime): This is the cable I used to turn an old iPad into a digital picture frame. The right-angle looks much neater than a straight cable, plus this one can shuttle up to 240 watts of power during charging.

Moft Magnetic Wallet Stand for $24 ($6 off with Prime): I like to carry as little as possible, preferably in my pockets. This nifty wallet attaches to MagSafe phones (iPhones 12 and newer), has room for two cards and has a pop-out stand for screen-viewing in either portrait or vertical orientation.

Samsung EVO Select microSD card (128GB) for $13 ($4 off): This Samsung card has been one of our recommended models for a long time. It's a no-frills microSD card that, while not the fastest, will be perfectly capable in most devices where you're just looking for simple, expanded storage. The larger-capacity 256GB model is on sale for $23, but the 128GB is a better gigs-to-dollars deal. 

Jisulife Life7 handheld fan for $23 ($6 off with Prime): This handy little fan is a must-have if you live in a warm climate or have a tropical vacation planned anytime soon. It can be used as a table or handheld fan and even be worn around the neck so you don't have to hold it at all. Its 5,000 mAh battery allows it to last hours on a single charge, and the small display in the middle of the fan's blades shows its remaining battery level.

Pebblebee Clip Universal for $25 ($10 off with Prime): This is our runner up pick for a rechargeable Bluetooth tracker. It’s ear-splittingly loud, has bright flashing LEDs and works with either Google or Apple’s finding networks.

Roku Streaming Stick HD for $18 ($12 off): If you don’t care about 4K (or your screen resolution isn’t that high anyway) you can still get the same simple-to-use Roku OS that we liked in our guide with this device. The best thing about Roku devices is the access to all the free content — and this is an affordable way to get it.

Amazon Fire TV Stick HD for $18 ($17 off): Here’s what we named the best budget streaming stick. At a price this low and only an HD resolution, you shouldn’t expect a premium picture, but if you just want a quick way to get your streaming apps up and running on a basic screen, this will do the thing.

Ring Indoor Cam for $25 ($25 off): While we thought the Blink Mini 2 was a better overall indoor camera in our guide, we do like the Ring app, which is ideal for beginners. Plus you get access to the Ring Neighbors app which is a fascinating glimpse into your neighborhood’s Ring-captured events.

JLab Go Air Pop+ for $17 ($13 off with Prime): JLab earbuds pop up in a few of our guides including the best running headphones and best budget buds. The Pop+ earbuds are smaller and lighter than the previous model, and the app’s preset EQ modes let you customize your sound. Total battery life with the case comes in at more than 35 hours.

Samsung Fit Plus 256GB for $23 (30 percent off): We named this thumbdrive one of the best SSDs you can buy. This configuration has 256GB of storage and read speeds of 400MB/s. It's also built to resist water, extreme temperatures, magnets and even radiation.

This article originally appeared on Engadget at https://www.engadget.com/deals/amazon-prime-day-tech-deals-under-25-save-on-blink-anker-roku-and-fire-tv-084136589.html?src=rss

The best Day 2 Prime Day speaker deals: JBL, Bose, Ultimate Ears and more

We're always ready to argue that high-quality speakers are a worthwhile investment, adding new dimensions to music and dialogue that make any kind of entertainment more enjoyable. Though Prime Day is almost over, our resident audiophiles are still sifting through Amazon for bargains on the best smart speakers, soundbars and portable bluetooth speakers. This October Prime Day, our list of the best deals includes brands like Anker, Bose, JBL, Amazon Echo and more. So if you're ready to hear when your favorite TV actors are scratching themselves, let's get started.

  • JBL Xtreme 2 for $150 ($30 off): This deal is a great way to get ahold of the JBL Xtreme 2, an old favorite from 2018 we still love. An Xtreme 2 can get louder than you'd expect from a portable speaker, putting out 40 watts at maximum, and stays charged for around 15 hours.

  • JBL Flip 6 for $100 ($30 off): The JBL Flip 6 is a solid choice for an all-around bluetooth speaker, performing well in any room or on the go. It sounds good at almost any frequency and volume, runs for 12 hours on a single charge and is nearly impossible to damage with falls, dust or water.

  • JBL Go 3 for $35 (30 percent off): The JBL Go 3 is a decent and highly affordable carabiner speaker for all your outdoor adventures — as is its sister product, the Go 3 Eco, which is made from recycled materials. It's obviously not the most powerful speaker at 4.2 watts, but it has a surprisingly good functional range. Plus, the design looks good on any belt or backpack.

  • Beats Pill for $119 (34 percent off): This Bluetooth speaker from Apple subsidiary Beats earned a score of 83 in our review and currently holds a spot in our buying guide. It’s not the best raw value on the market, and it can struggle at maximum volume, but it generally pumps out strong bass without sounding imbalanced. A stylish and water-resistant design, ample battery life and the ability to play lossless audio over a USB-C cable add to the appeal. This sizable discount matches the lowest price we’ve tracked.

  • Ultimate Ears Miniroll for $47 (41 percent off): Miniroll is the smallest speaker from Ultimate Ears, but it punches far above its weight, starting with UE's trademark massive volume buttons. While small enough to fit in a jeans pocket, its combination of a driver and radiator manages about 85 decibels. A Miniroll can run for about 12 hours on a single charge.

  • Ultimate Ears Boom 4 for $95 (37 percent off): The UE Boom 4 is a balanced speaker that does well anywhere. Take it camping (it's waterproof and a charge lasts for 15 hours), to a party (it puts out loud 360 degree sound) or make it part of a permanent home system by chaining it with other UE speakers — one of these plus two Minirolls or Wonderbooms would come pretty close to full surround sound.

  • Ultimate Ears Everboom for $231 ($39 off): The Everboom is the middle ground of the UE line, with more powerful output than the Wonderboom and more portability than the Hyperboom. Its 360 degree sound pairs with an Outdoor Boost feature to work better outside, though it isn't quite as impressive in the middle ranges.

  • Bose SoundLink Flex for $99 (34 percent off): We've rarely seen the Bose SoundLink Flex this cheap, so now is the time to snap up this high-fidelity outdoor speaker. It's small enough to carry in one hand and can be operated from up to 30 feet away via the Bose Connect app. We've also found it simple and fun to use for hands-free phone calls during breaks in the music.

  • Bose SoundLink Revolve+ for $179 (40 percent off): The SoundLink Revolve+ line, Bose's original upright 360-degree speakers, continue to pack a punch. This current model features a 17-hour battery life, IP55 water resistance and the ability to connect to a smart speaker to extend your virtual assistant's range.

  • Bose SoundLink Max for $299 ($100 off): The Bose SoundLink Max may put you in mind of a classic boombox, with its detachable handle and thudding base. But inside it's all modern, with a 50-watt output, an effective range of 52.6Hz and a 20-hour rechargeable battery. It even comes with a 3.5mm AUX input to connect to a turntable, if you really want to embrace your inner 90s DJ.

  • Anker Soundcore 2 for $28 (38 percent off): This larger speaker doesn't look like much, but it's tough, water-resistant and versatile. It's got a broad range of optimal pitch, effective across 70 Hz from bass to treble, and 12 watts of output. While it's portable and sounds good outdoors, its wide design means it can also substitute for a soundbar in your home theater.

  • Soundcore Select 4 Go for $18 (20 percent off): The Soundcore Select 4 Go weighs only 9.3 ounces, which makes the rest of its specs even more impressive: 20 hours of battery life, IP67 waterproofing and sound that fills rooms. It even sounds pretty good in compact outdoor spaces, more than capable of serenading an outdoor desk or livening up a pool party.

  • Soundcore Motion 300 for $56 (30 percent off): The Soundcore Motion 300 is a full-frequency champ, with clean sound in the higher ranges and reasonably heavy bass. Its adaptive audio feature changes output depending on whether the speaker is currently lying down, standing on end or hanging from your belt loop. It's also small and light enough to carry in your pocket or clip to your backpack.

  • Marshall Emberton II for $100 (44 percent off): Marshall, the old warhorse of the audio world, continues to crush it with the portable and bluetooth-ready Emberton II. Although it looks like an antique, it's anything but, with 360-degree sound and over 30 hours of battery life from a single charge — all weighing a little more than a quarter of a pound.

  • Marshall Acton III for $200 ($100 off): Marshall recently re-engineered the Acton's speaker setup by angling the tweeters outward. It paid off, especially in the Acton III, which now delivers a pleasingly wide soundscape. At 6.3 pounts, it's not technically portable, but the design makes it easy to move around — and for the eco-conscious, it's made of 70 percent recycled materials.

  • Amazon Echo Pop for $25 (38 percent off): The Echo Pop is Amazon's smallest and cheapest smart speaker, resembling an Echo Dot sliced in half. It's a little quiet, and probably best for extending Alexa's range rather than serving as the primary host for your virtual assistant. In a smaller room, though, this is as convenient and clear-sounding as any other Echo you'll use.

  • Amazon Echo Spot for $45 (44 percent off): Other than perhaps the Pop, no Amazon Echo fits better on a bedside table than the Spot. Its user-friendly design incorporates both a speaker and a digital display — so it's recognizable as a classic alarm clock, but with much more information on the screen and far better sound quality. This is the lowest price we've ever seen it sell for.

  • Sonos Era 100 for $180 ($20 off): The Sonos Era 100 is a fantastic smart speaker for an even better price. It's not only loud — it also sounds good at any volume, no matter what platform you're streaming audio from. It can connect via bluetooth or physical lines, and uses TruePlay to tune the sound to your current location using included mics.

  • Sonos Era 300 for $379 ($100 off): In our full review of the Sonos Era 300, we found that it's easy to set up and sounds incredible. It includes the exciting spatial audio feature that makes music sound like it's coming from everywhere — while it doesn't always work, it's exhilarating when it hits. The Era 300 can even automatically tune sound to your location, and you no longer need an iPhone for this feature to work.

  • JBL Bar 300 for $250 (38 percent off): The Bar 300, part of JBL's 2023 soundbar explosion, is a mighty yet cheap soundbar with an integrated subwoofer. Despite being small, it manages to create a theatrical experience by working both Dolby Atmos and MultiBeam. Its voice sharpening algorithm is especially good at making dialogue clearer (for those of us who always have to put on the subtitles).

  • Amazon Fire TV Soundbar Plus for $150 (40 percent off): One of the cheapest soundbars you'll ever see, the Fire TV Soundbar Plus provides a noticeable boost to your TV's audio quality, even if it doesn't reach Dolby Atmos heights. It's simple, but that makes it a breeze to set up — all you have to do is plug in one HDMI cable.

  • Sony Bravia Theater Bar 6 for $498 ($202 off): The Sony Bravia Theater Bar 6 is part of Sony's Dolby Atmos soundbar lineup. It stands out from that line as a great entry point, balancing theatrical sound with defined dialogue by adjusting outputs through machine learning. It's capable of transforming normal stereo into surround sound through automatic up-mixing.

  • Roku Streambar for $69 (31 percent off): The Roku Streambar is already affordable, but this deal puts it within anyone's reach. It's also economical in terms of space — as we noted in our full review, it's about the size of an egg carton, but still manages to give off near-surround sound.

This article originally appeared on Engadget at https://www.engadget.com/audio/speakers/the-best-day-2-prime-day-speaker-deals-jbl-bose-ultimate-ears-and-more-083538729.html?src=rss

The best Prime Day vacuum deals: Save on machines from iRobot, Shark, Dyson and others

It's day 2 of October Prime Day, and Amazon still has plenty of heavily discounted traditional and robotic vacuums in stock. We're hoping this article can do more than just save you money — it's also designed to help you with the fiddliest vacuum-related decisions. Should you go corded, cordless or robotic? Dyson, Tineco or Shark? Are there any decent robot vacuums that aren't Roombas? (Yes.) The Big Deal Days sale ends tonight, but until the very end, we'll search for discounts as tirelessly as an automated vacuum scours your floors for dirt, and post all the best deals here.

  • Shark AV2501AE AI Robot Vacuum for $600 ($50 off): If you like the look of the AV2501S but have even more space to clean, the AV2501AE is also on sale. Its self-empty base can go a full 60 days before you have to dump it out, so it's ideal for large spaces, complex homes or areas that see heavy use. It's got the same features otherwise, including LiDAR mapping and two hours of autonomous work.

  • Shark PowerDetect NeverTouch for $450 (36 percent off): This robotic mop/vacuum combo is engineering so you'll almost never need to revisit it after you set it up. It can clean its own mop, refill its own water tank and empty its own dustbin for up to 30 days at a time. It's also equipped with air jets that blast dirt out of corners the vacuum can't fit into.

  • Dreame X40 Ultra Robotic Vacuum for $665 (45 percent off): Yes, it's on the expensive side, but the Dreame X40's performance earns every penny. It's another two-in-one combo, mixing a powerful vacuum cleaner with a precise mop to diligently scrub stains. Its inner workings are engineered to keep the wet and dry messes from touching, which can cause gross leaks in lesser vacuums.

  • Shark Matrix Plus 2-in-1 for $300 (57 percent off, Prime exclusive): The Shark Matrix Plus takes the robot vacuum concept even further by working a mop into the design for hands-off wet cleaning. This model is self-cleaning, self-emptying, self-charging and capable of tackling ground-in stains on hard floors.

  • iRobot Roomba 104 Vac for $150 (40 percent off, Prime exclusive): This entry-level Roomba is a good pick for anyone who's new to owning a robot vacuum. It features a multi-surface brush and an edge-sweeping brush to clean all types of flooring, and it uses LiDAR navigation to avoid obstacles as it goes. The iRobot mobile app lets you control the robot, set cleaning schedules and more.

  • iRobot Roomba Plus 504 for $380 (49 percent off): For those looking to upgrade to a more advanced robot vacuum, the Roomba Plus 504 is a great next step. It can clean almost anything that might land on a home floor, and if it can't clean it, it can steer around it. Two brushes and strong suction get at tougher stains, and it even includes an app you can use to set cleaning zones and change suction force remotely.

  • Roborock Q10 S5+ Robot Vacuum and Mop for $300 ($100 off): The Roborock Q10 S5+ is another great option for a vacuum-mop combo. It's skilled at knowing what type of floor it's on and deploying or retracting the mop appropriately, and comes with precision LiDAR mapping. You can change its settings remotely from a paired app.

  • Roborock Qrevo Edge S5A Robot Vacuum and Mop for $650 (35 percent off): The higher-end Roborock choice has two brushes positioned to keep hair from tangling in either roll. The Qrevo Edge features strong suction, hot-water mopping and 60 days of completely hands-off cleaning. It can even mop and vacuum in the same cleaning session by lifting the mop whenever it notices a carpet.

  • Ecovacs Deebot X9 Pro Omni Robot Vacuum and Mop for $900 (31 percent off): Evocacs is a high-end robot vacuum provider to be sure, but this deal makes the X9 Pro accessible. It cleans its mop in real time so dirty water never touches your floor and comes with a lift system that lets it mop and vacuum simultaneously. The X9 also has 16,600Pa of suction in case you've got some really ground-on stains.

  • Levoit LVAC-300 cordless vacuum for $220 (37 percent off, Prime exclusive): One of our favorite cordless vacuums, this Levoit machine has great handling, strong suction power for its price and a premium-feeling design. Its bin isn't too small, it has HEPA filtration and its battery life should be more than enough for you to clean your whole home many times over before it needs a recharge.

  • Shark NV352 Navigator Lift-Away for $130 (35 percent off): If you want the excellent steering and modular design of the Navigator Lift-Away but don't need as much storage in the chamber as the Deluxe offers, the basic NV352 is cheaper and just as thorough. This slightly smaller unit still comes with a HEPA filter, swivel steering and a detachable handheld vacuum, plus toggleable carpet and hardwood settings.

  • Shark CarpetXpert HairPro for $280 ($90 off): Not all vacuums need to reinvent the wheel. The Shark CarpetXpert HairPro is the perfect midrange option, with a large brushroll for getting pet hair and other allergens out of your carpets. It's designed internally to suction and store hair without clogging, making it an even better fit for homes with pets.

  • Shark Cordless Vacuum Cleaner for $200 (43 percent off): If you're looking for a lighter vacuum that's more maneuverable, the Shark Cordless Vacuum Cleaner might fit the bill. It's easy to steer with a self-cleaning brushroll and surprisingly strong suction. Being slimmer makes it good for fitting under furniture and around tight corners.

  • Dyson Ball Animal Total Clean Upright Vacuum for $400 (39 percent off): Dyson is still the king of reinventing vacuums, and the bagless, hyper-maneuverable Ball Animal is a blast to use. The Ball design is based on ease of steering, but the hidden MVP is the sealing — from the head to the canister, not a hair is getting out of this one once it's in.

  • Dyson V11 Origin Cordless Vacuum for $400 (37 percent off): Dyson's take on the now-classic cordless vacuum design is another winner, with three power settings, a built-in HEPA filter and about an hour of continuous operation per charge. You can also detach the shaft and use it as a handheld vacuum as needed.

  • Dyson V15 Detect Plus for $570 (33 percent off): Our top pick for the best cordless vacuum on the market right now, the V15 Detect has some of the strongest suction power you'll find in a stick vacuum, plus a lightweight design and a dustbin that can hold more dirt and debris than it might seem. This model comes with five cleaning attachments, including the Fluffy Optic cleaner head that has LEDs to illuminate the floor as you're vacuuming so you can better see where all the dust bunnies are.

  • Eureka Stylus Elite NEC490BL Cordless Stick Vacuum for $190 ($90 off): Another extremely strong entry into the field of budget-friendly cordless vacuums, the Eureka Stylus Elite comes with its own self-emptying station — just plug the holding tank into the stand, and the mechanism does the rest. It also includes an anti-tangle brush roll, five layers of HEPA filtration and three modes that let you decide whether to prioritize power or battery charge length.

This article originally appeared on Engadget at https://www.engadget.com/deals/the-best-prime-day-vacuum-deals-save-on-machines-from-irobot-shark-dyson-and-others-151504087.html?src=rss

The best Prime Day SSD deals still available on Day 2: Save on Samsung, microSD cards for Switch 2 and more

A portable storage device can make a world of difference to intensive processing tasks, from running massive video games — which feels like all of them these days — to core operating system functions. A solid-state drive (SSD) gives your hard drive more bandwidth than it comes with by default, making huge chunks of data easier to digest and keeping your device from running too hot. Although October Prime Day is nearly over, you can still take advantage of our list of deals on SSDs, portable SSDs and microSD cards. Not only are these some of the best products in the field, but their prices are lower than they're likely to be for some time.

  • Crucial BX500 1TB 3D NAND SATA 2.5-inch Internal SSD for $69 (28 percent off): The BX500 is Crucial's budget-conscious SSD option, but that doesn't mean it disappoints. This internal solid state drive cuts down on battery consumption and improves processing with read speeds reaching 540MB/s. It comes with a three-year warranty, too.

  • Samsung 990 Evo Plus 1TB for $60 (43 percent off): This is an incredible deal on an internal SSD from a reliable brand. All capacities of the Samsung 990 Evo Plus are currently on sale, but even the 1TB option can visibly boost your performance with top read speeds of 7,250MB/s. There's no heatsink, but nickel plating on the controller reduces both heat output and energy use.

  • Samsung 990 PRO 2 TB for $140 (33 percent off): Samsung's 990 Pro series represents a massive leap forward for the brand, cutting energy costs by around half while boosting speeds up to at least 7,000MB/s write and 5,000MB/s read. This version comes with 2TB of storage and its own built-in heatsink.

  • Samsung SSD 9100 PRO 4TB for $370 (35 percent off): The 9100 Pro series comes with speeds and capacities that dwarf even the 990 Pro. If you need to improve your speeds while training large AI models or simply playing massive games, this is about the most power commercially available right now.

  • Samsung Fit Plus 256GB for $23 (30 percent off): The Samsung Fit Plus isn't just the best thumb drive on the market right now — it's one of the best SSDs, period. This deal gets you 256GB of storage and read speeds of 400MB/s for almost unfathomably cheap. It's also built to resist water, extreme temperatures, magnets and even radiation.

  • Samsung 870 EVO SATA III Internal SSD 1TB for $95 ($22 off): Samsung's 870 Evo series consists of some of the best entry-level SSD storage available. While it's not quite as fast as the Samsung 990s above, it still posts read and write speeds around 550MB/s, enough for a visible difference when organizing a media library. It's also way more affordable.

  • Kingston Fury Renegade G5 for $170 (48 percent off): For those who need the most power available — especially on machines working with AI — Kingston Fury Renegade is an affordable way to access fifth-gen PCle power. With working speeds over 14,000MB/s and backward compatibility, you'll be well-prepared for the next generation of processing.

  • WD_BLACK 2TB SN7100 for $130 ($30 off): The SN7100 is a strong entry point to WD_BLACK's extremely powerful Gen 4 SSDs. It's built for gaming, with read speeds of up to 7,250MB/s and write speeds of 6,900. The 2TB edition has the best markdown, but 1TB is more affordable overall if you're on a tight budget — and both can easily run a whole operating system in parallel.

  • WD_BLACK 8TB SN850X for $544 (42 percent off): Honestly, we can't think of a lot of people who need an SSD with 8TB of storage — but if you're one of those people, this is the deal of a lifetime. The SN850X is both capacious and high-functioning, including both a heatsink and a digital dashboard you can use to monitor its performance. The smaller, cheaper versions are also marked down.

  • Lexar 1TB NM790 SSD for $65 (32 percent off): You'll see Lexar a lot on this list, and for good reason — it's a good first stop for affordable, well-reviewed storage. The NM790 includes a heatsink and delivers speeds of 7,400MB/s read and 6500MB/s write. It's highly power-efficient for a 4th-gen SSD and even includes a five-year warranty.

  • SanDisk 2TB Extreme Portable SSD for $150 (29 percent off): The SanDisk Extreme line of portable SSDs provides a great middle ground in both price and performance. Read speeds of 1,050MB/s are enough for transferring most files you'll encounter day-to-day. Its external design holds up too, with a large carabiner loop, IP65 waterproofing and dustproofing and drop protection as high as three meters.

  • Kingston SX1000 1TB High Performance for $75 (35 percent off): If you can't swing a Crucial X9 or X10 right now, Kingston offers a much more affordable alternative. The SX1000 can handle both PC backups and gaming storage with ease, nearly matching the X9 in our speed tests. It's also easy to carry around, though keep a tight grip as it's not officially rated for any drop height.

  • Seagate Storage Expansion Card 2TB for $190 (47 percent off): This Seagate SSD is specifically for expanding storage on the Xbox Series X and S, and it's designed to meet Xbox specs exactly. You'll get exactly the same performance booting a game from this card as you would from internal Xbox storage, which makes data management infinitely easier.

  • Lexar 2TB Armor 700 for $130 (38 percent off): The Armor 700 is Lexar's USB 3.2 Gen 2x2 portable SSD, and it's on the leading edge of that hardware generation, hitting 2000 MB/s in both read and write speeds. With a cable compatible with both USB-A and USB-C, it fits basically any hardware from PCs and Macs to gaming consoles, and it's even rated for drops of up to three meters.

This article originally appeared on Engadget at https://www.engadget.com/deals/the-best-prime-day-ssd-deals-still-available-on-day-2-save-on-samsung-microsd-cards-for-switch-2-and-more-170039333.html?src=rss

Sackbird Studios emerges from the Xbox layoffs

When Microsoft and Xbox announced layoffs numbering in the thousands earlier this year, it meant the end for a whole bunch of upcoming game projects. Many studios were forced to downsize, and some shuttered entirely, as a result. Luckily, some enterprising developers are turning the bad news into something positive.

A group of former devs from ZeniMax Online Studios, which made The Elder Scrolls Online and scrapped looter shooter Blackbird, have banded together to form a new company called Sackbird Studios. Perhaps unsurprisingly, the team is going for the employee-owned, self-funded route. "With no outside investors and full creative control, the team is focused on building great games—on their own terms," the announcement states. 

Right now, the senior team numbers fewer than ten people, including CEO Lee Ridout and COO David Worley. Sackbird is already in active development on its first project, but the crew isn't sharing any details other than that the game will be available on both PC and consoles.

This article originally appeared on Engadget at https://www.engadget.com/sackbird-studios-emerges-from-the-xbox-layoffs-214000161.html?src=rss

Apple removed an app that archives videos of ICE arrests

Apple has removed Eyes Up, an app that collects and archives videos of Immigration Customs and Enforcement arrests, 404 Media reports. The app's removal follows similar action taken against ICEBlock last week, an app that tracks ICE activity in an attempt to offer real-time alerts of when and where arrests are happening. Unlike ICEBlock, though, Eyes Up's main purpose is to serve as an archive, not a tool for eluding government agents.

The app, which is still available via the web and the Google Play Store, archives videos of ICE arrests from a variety of different sources, and plots them on an interactive map. Users can submit their own videos for inclusion, and tap or click on individual map pins to view videos and download them for later use. "Our goal is government accountability, we aren’t even doing real-time tracking," an Eyes Up administrator told 404 Media. Ultimately, saved videos could prove useful in court, especially in response to possible ICE misconduct.

Apple says it removed Eyes Up because it violated the company's policy around "objectionable content," according to the report, and because it received information from law enforcement that the app is used "to provide location information about law enforcement officers that can be used to harm such officers individually or as a group."

Engadget has contacted Apple for more information on Eyes Up's removal from the App Store. We'll update this article if we hear back.

Apple reportedly received similar information to spur the removal of ICEBlock from the App Store, including a direct request from Attorney General Pam Bondi, Fox Business reports. The fact that Eyes Up was also removed suggests that Apple is casting a wider net than just banning apps that help pinpoint the location of ICE activity.

Google has been removing similar apps on the Play Store, too. The company pulled an app called Red Dot that also plotted ICE activity on a map, one of several apps that were removed because they shared the location of a "vulnerable group."

This article originally appeared on Engadget at https://www.engadget.com/apps/apple-removed-an-app-that-archives-videos-of-ice-arrests-212946540.html?src=rss

Nintendo Switch 2-compatible microSD Express cards are on sale for the first time thanks to Prime Day

It's safe to say the Nintendo Switch 2 is the game console to get this year, and if you already got your hands on one, you've probably loaded it up with all your old Switch games and new Switch 2 games. If you haven't thought about adding more storage to the console, now's the time to do so. The Switch 2, unfortunately and inconveniently, cannot work with just any old microSD card — it only works with newer microSD Express cards. But thanks to Prime Day, you can actually pick up one of these new cards on sale. The most affordable of the bunch is this 128GB PNY microSD Express card, which is 15 percent off for Prime members and down to $38.

Engadget's Jeff Dunn has been testing microSD Express cards since the Switch 2 launched. The best microSD Express card for Switch 2 at the moment is really the one you can most easily afford. While the cards he's tried out so far didn't perform identically in our benchmark tests, the differences in overall performance and load times will be tough for most people to notice. Thankfully, the ones he's tested so far have been good — there isn't a bad one in the bunch, and while the most consistent performer was the SanDisk microSD Express card, you won't really sacrifice by getting a different one. In fact, at least in the case of Prime Day deals, you'll be gaining by saving some cash.

PNY's card in particular was actually slightly faster than SanDisk's in our testing when it came to moving games from the card back to the Switch 2's internal storage. However, it was a bit slower in writing games to the card itself. That just means you may wait a few extra minutes before you can open Mario Kart World and get to racing, but for most people, the difference will be negligible.

Also on sale for Prime Day are two configurations of Lexar's Play Pro microSD card. The 256GB version is down to $50, while the 512GB model is on sale for $100. That's 17 percent off each and the lowest they've been. If you're hoping to make a one-and-done purchase and you already plan on packing your console with the best Switch 2 games, we'd recommend getting the card with the highest capacity that's still within your budget.

This article originally appeared on Engadget at https://www.engadget.com/deals/nintendo-switch-2-compatible-microsd-express-cards-are-on-sale-for-the-first-time-thanks-to-prime-day-134147311.html?src=rss

The 59 best Amazon Prime Day deals under $50 from Anker, Ring, Lego, Roku and others

This is technically the third Prime-related sale of the year, after March’s spring sale and the official Prime Day in July. Amazon calls this one Prime Big Deal Days, but to you, me and most everyone else, it’s the October Prime Day sale. But it ends tonight. This guide covers tech and gadgets that go for under $50 after the discount, but only ones we recommend. These are the batteries, mice, earbuds, speakers, wall chargers and other accessories that the Engadget team has tested for our guides and reviews. Read on for Engadget’s guide to the best Prime Day tech deals for under $50. 

Apple MagSafe charger (25W, 2m) for $29 ($20 off): The latest version of Apple's MagSafe puck is Qi2.2-certified and supports up to 25W of wireless power when paired with a 30W adapter. The two-meter cable length on this particular model gives you more flexibility on where you can use it: in bed, on the couch, at your desk and elsewhere. (Note: the discount here has fluctuated between $29, $35 and $43 throughout the sale.) 

Moft Magnetic Wallet Stand for $24 ($6 off with Prime): I like to carry as little as possible, preferably in my pockets. This nifty wallet attaches to MagSafe phones (iPhones 12 and newer), has room for two cards and has a pop-out stand for screen-viewing in either portrait or vertical orientation.

PNY microSD Express (128GB) for $39 ($6 off with Prime): If you’ve gotten yourself a Switch 2 (or planning to gift one for the Holidays) you may want to get a couple microSD Express cards. They’re the only type that work with the new console, which you can read all about in our guide to Switch 2 storage. This is one of the cards we recommend.

Lexar 256GB Play PRO microSD Ex for $50 ($10 off with Prime): Here’s another of our picks for a Switch 2-compatible storage card. The 512GB option is on sale too, but it’s more than $50.

Audible subscription (three months) for $3 ($42 off): From now through mid-December, you can get Amazon’s audiobook subscription for just a dollar a month for three months. Note that it will auto-renew at $15 per month after that, but you can cancel at any point.

Moft Folding Sit-Stand Laptop Stand for $48 ($12 off with Prime): I take this with me when I have to work someplace away from my standing desk. It holds a 16-inch MacBook Pro 10 inches off a desk, which is just enough for you to stand up and work. It also configures into four other positions for better ergonomics as you sit. It’s one of our favorite MacBook accessories.

UGREEN Nexode Pro 65W USB-C Flat Charger for $43 ($13 off with Prime): One of our picks from our guide to fast chargers, this Ugreen fella has three ports (one of which is USB-A) and a 65-watt max power output. The folding prongs make it even more compact. Just note that it’s a bit wide and may block adjacent outlets in a crowded power strip.

Anker USB C Charger (Nano II 65W) for $26 ($14 off with Prime): Anker makes some of our favorite charging accessories. This one has three USB ports, two Type C and one Type A, plus a max speed of 65 watts.

UGreen Revodok Pro 109 USB-C Hub for $37 ($18 off with Prime): The top pick in our guide to the best USB-C hubs has a good array of ports, including an HDMI 2.0 connection that supports 4K monitors at 60Hz, plus three USB-A ports, Ethernet and one USB-C (plus another for delivering 90W of power to your device.

Anker Nano Charger, USB-C 30W charger for $13 ($4 off with Prime): Here’s a tiny but mighty wall adapter that we like for iPhones (but it would work for an iPad too). It can pass on 30 watts of power to your device and looks nice doing it in five different pearlescent shades.

Instant Pot Vortex 2-QT Mini for $38 ($22 off with Prime): The budget model from our air fryer guide may not be large but its two-quart basket is enough to reheat leftovers for two or cook up a batch of frozen appetizers. And, because of its small size, it doesn’t take up a ton of space on your countertops — ideal for a small kitchen.

Elgato Stream Deck Mini for $50 ($10 off with Prime): We like Elgato gear for game streaming, but the handy shortcut deck can also be used for your nine to five. This six-button box can give you better control over PowerPoint presentations, video conferencing calls and spreadsheet wrangling.

INIU MagSafe Qi2 power bank for $34 ($16 off with Prime): This is the budget pick in our guide to the best MagSafe batteries. Not only can it refuel a dying iPhone (12 or newer) wirelessly, it comes with its own USB-C cable (that doubles as a handy carrying strap) so you can charge up other devices, too.

Amazon Fire TV Stick 4K Max for $40 ($20 off): Amazon's most powerful streaming dongle supports 4K HDR content, Dolby Vision and Atmos and Wi-Fi 6E with double the storage of cheaper Fire TV sticks. It earned an honorable mention in our guide to streaming devices and also happens to make a good retro gaming emulator.

Lego Icons Dried Flower Centerpiece for $35 ($15 off with Prime): Who doesn’t love a good Lego set? Only people who don’t like fun. This floral centerpiece looks good enough to stick on a dining table and it’ll never die.

Lego Star Wars Advent Calendar 2025 for $31 (30 percent off): 'Tis the season for advent calendars. They've flooded the internet, as they usually do this time of year, and there are plenty to choose from (and stock up on) before we get to December. Lego has a bunch, and this Star Wars one will be fun for everyone, not just kids, to open up each day at the end of the year.

—> Check out more sets in our Prime Day guide to Lego deals.

Anker USB-C to USB-C cable (10FT, 100W) for $9 ($3 off with Prime): Having a bad cable is almost as bad as not having a cable at all. We’re big fans of Anker’s cords. This one is a generous 10 feet and can deliver up to 100W of power. While it can transfer data, it does so slowly, so don’t grab this one for that purpose. This is $1 more than it sold for as a Prime-exclusive in July.

Chipolo Pop Bluetooth tracker for $25 ($4 off): If you lose stuff, stop it with a Bluetooth tracker like this. The Pop is our top pick in our guide. It works with either Apple’s Find My app or Google’s Find Hub app, calling on iPhone or Android phone users respectively to anonymously ping your lost stuff so you can find it.

Pebblebee Clip Universal for $25 ($10 off with Prime): This is our runner up pick for a rechargeable Bluetooth tracker. It’s ear-splittingly loud, has bright flashing LEDs and works with either Google or Apple’s finding networks.

Samsung Galaxy SmartTag2 for $20 ($10 off with Prime): Our favorite Bluetooth tracker for Samsung users is one of the best-looking fobs we tried. It’s got a wide finding network, drawing on nearby Samsung phones to ping your lost items (though not as large as Google or Apple’s networks).

Blink Video Doorbell for $35 ($35 off): True, Amazon just announced new Blink devices, but those won’t hit the market until after Prime Day is over. If you want a video doorbell right now at an impressively low price, this should serve. We’ve tested Blink security devices before and have been impressed by what you get for such a small price.

Blink Video Doorbell & Blink Mini 2 for $40 ($70 off): Here’s a bundle that combines a Blink Doorbell and a Mini 2 security camera. But again, new Blink cameras are on their way, so only get this if you're ok with last year’s tech.

Ring Battery Doorbell for $50 ($50 off): At $49.99 this juuust qualifies as an under $50 tech deal. If you don’t have doorbell wires at your front entrance, you can still have a camera to capture all the package deliveries and neighborhood animal sightings with the Ring Battery Doorbell. It records video in HD with more vertical coverage than the last model, so you can see people from head to toe. Just note that newer Ring devices are on the way. 

Blink Mini 2 security cameras (two-pack) for $35 ($35 off): This is currently the top budget pick in our guide to the best security cameras. The Mini 2 is a great option for indoor monitoring or you can put it outside with a weatherproof adapter, but since it needs to be plugged in, we like it for keeping an eye on your pets while you're away and watching over entry ways from the inside.

Blink Mini 2 security cameras (three-pack) for $50 ($50 off): A three pack is also on sale and squeezes in just under the $50 mark. Or you can just get one camera for $20

—> Want to spend no more than $25? Check out our list of super cheap Prime Day tech.

Anker 622 5K magnetic power bank with stand for $28 ($20 off with Prime): This 0.5-inch thick power bank attaches magnetically to iPhones and won't get in your way when you're using your phone. It also has a built-in stand so you can watch videos, make FaceTime calls and more hands-free while your phone is powering up.

J-Tech Digital Ergonomic Mouse for $17 ($7 off with Prime): This is the budget pick in our ergonomic mouse guide thanks to its vertical format, programmable buttons and nifty RBC lights (which you can turn off).

Razer Basilisk V3 gaming mouse for $30 ($40 off): Some prefer a wired connection when playing games. Razer’s Basilisk V3 is our top budget pick for a wired mouse in our gaming mouse guide. It’s comfortable, well-built, accurate and a good value — particularly with a Prime Day discount.

OtterBox Made for Kids Case for iPad (A16) for $49 ($21 off with Prime): Where other cases failed, this one has managed to keep my third grader’s iPad alive and functioning. It’ll fit the newest standard iPad or the 10th generation model that came before it.

Ring Indoor Cam for $25 ($25 off): While we thought the Blink Mini 2 was a better overall indoor camera in our guide, we do like the Ring app, which is ideal for beginners. Plus you get access to the Ring Neighbors app which is a fascinating glimpse into your neighborhood’s Ring-captured events. Just note that a new Ring indoor model was just announced

Amazon Smart Plug for $13 ($12 off): We named this the best smart plug for Alexa users because it hooks up painlessly and stays connected reliably. Use it to control lamps or your holiday lights using programs and schedules in the Alexa app, or just your voice by talking to your Echo Dot or other Alexa-enabled listener.

Ultimate Ears MINIROLL Bluetooth speaker for $48 ($32 off with Prime): Ultimate Ears speakers make a couple of appearances in our guide to the best Bluetooth speakers. The Miniroll is the smaller sibling of the UE Wonderboom. You’ll sacrifice a little in the sound department, but it maintains a similarly durable waterproof and dustproof build.

Anker Nano 3-in-1 Portable Charger for $32 ($13 off with Prime): It’s a wall charger! It’s a portable battery! It has its own USB-C cable! In short, this handy power bank is clever and compact, which is why it’s one of our favorites.

Anker Nano portable charger for $20 ($10 off with Prime): It looks like an oldy timey lipstick case and can deliver a partial refill to any small device with a USB-C port. We named it a good pick after testing it for our battery guide.

Twelve South AirFly SE for $28 ($12 off with Prime): We recommend this in our father’s day gift guide and a couple of our travel guides. If you know you’re travelling on a plane with screens in the backs of the seats, you may want Twelve South’s gadget. It lets you connect your wireless earbuds to the aux jack. Also a good pick for gym equipment.

Levoit Mini Core-P air purifier for $40 ($10 off with Prime): This is the mini version of the top pick in our guide to air purifiers. It has a three-stage filter (pre, activated carbon and particle filters) though that particle filter is not a true HEPA filter. But it’s rated at 250 square feet and can help clear the air in your office or other small room.

8Bitdo Ultimate Bluetooth controller (Switch 2) for $43 ($27 off with Prime): If you’ve got a Switch 2 and are looking for a good controller to go with it, we think this is a good one. Recommended in our guide to the best Switch 2 accessories, it’s got an Xbox style configuration with the left stick placed higher on the game pad, which some prefer. The lowest price we tracked before this is $50.

Anker 555 USB-C Hub for $36 ($14 off with Prime): To give your iPad (or even your laptop) more connection options, pick up this USB-C hub. It’s the model we liked best for our guide to MacBook accessories and adds an HDMI port, an SD card reader, Ethernet jack and two USB-A ports. It also has one data USB-C port and a pass through power delivery USB-C port, along with a built-in USB-C cable.

Echo Pop smart speaker for $25 ($15 off): The half sphere Pop is the most affordable Echo speaker in Amazon’s lineup. The sound won’t be as full as its larger siblings, but will do a fine job of bringing Alexa’s help to smaller rooms. Just note that it went as low as $18 for Black Friday and October Prime Day last year.

Elden Ring (PS5) for $30 ($20 off): If you somehow haven’t yet played the action-RPG Elden Ring, here’s a chance to do so for less money. It’s challenging yet accessible if you want plus it’s darkly funny and one of our favorite games.

Final Fantasy VII Rebirth (PS5) for $35 ($15 off with Prime): We gave this game a favorable review last year. But just note that you’ll get more out of it if you’ve played Final Fantasy 7 Remake.

—> For more video game deals, check out Engadget's Prime Day gaming roundup.

Belkin Carrying Case for Nintendo Switch 2 for $25 ($5 off with Prime): While this model doesn’t have the battery pack like Belkin’s charging case that we reviewed, it will still offer more than enough protection for everyday bumps and tumbles just like its more expensive counterpart.

Belkin Apple AirTag holder for $15 ($5 off with Prime): The best thing about Apple’s AirTags are their ability to rope in most any nearby iPhone to anonymously hunt for lost trackers. The worst thing is probably the tiny, slippery disk shape that can’t attach to anything without some help. This is the help we suggest in our iPhone accessories guide.

Ultimate Ears Wonderboom Play speaker for $48 ($42 off with Prime): This is a relative of the Wonderboom 4, one of our favorite Bluetooth speakers. It only has one driver and passive radiator, while the Wonderboom 4 has two of each. The battery life isn’t quite as long here, either (10 hours compared to 14). But this one is currently half the price of its sibling.

Samsung Fit Plus 256GB for $23 (30 percent off): We named this thumbdrive one of the best SSDs you can buy. This configuration has 256GB of storage and read speeds of 400MB/s. It's also built to resist water, extreme temperatures, magnets and even radiation.

Roku Streaming Stick HD for $18 ($12 off): If you don’t care about 4K (or your screen resolution isn’t that high anyway) you can still get the same simple-to-use Roku OS with this device. The best thing about Roku streaming sticks is the access to all the free content — so this is an affordable way to get it.

Belkin 45W Dual USB C Charger Block for $29 ($11 off with Prime): Members of my family fight over this handy wall charger. It has exactly what you need, two USB-C ports and speedy, 45W charging, perfect for juicing up a phone and tablet in tandem.

Leebein 2025 electric spin scrubber for $38 ($32 off with Prime): This is an updated version of the electric scrubber we love that makes shower cleaning easier than ever before. It comes with seven brush heads so you can use it to clean all kinds of surfaces, and its adjustable arm length makes it easier to clean hard-to-reach spots. It's IPX7 waterproof and recharges via USB-C.

Blink Outdoor 4 security camera for $35 ($45 off): We named this the best choice for Alexa users in our guide to security cameras. It works seamlessly with Alexa devices like the Echo speakers and Show displays. Plus it can run for up to two years on a set of AA batteries and we found the motion detection to be spot on.

Jisulife Life7 handheld fan for $23 ($6 off with Prime): This handy little fan is a must-have if you live in a warm climate or have a tropical vacation planned anytime soon. It can be used as a table or handheld fan and even be worn around the neck so you don't have to hold it at all. Its 5,000 mAh battery allows it to last hours on a single charge, and the small display in the middle of the fan's blades shows its remaining battery level.

Anker Soundcore Select 4 Go speaker for $23 ($12 off with Prime): This is one of our top picks for Bluetooth speaker. It gets pretty loud for its size and has decent sound quality. You can pair two together for stereo sound as well, and its IP67-rated design will keep it protected against water and dust.

Anker Soundcore 2 Portable Bluetooth Speaker for $28 ($17 off with Prime): This small speaker was a past pick in our guide to the best Bluetooth speakers. It’s waterproof and goes for 24 hours on a charge. We found the sound to be surprisingly big for its size.

Amazon Echo Spot for $45 ($35 off): Amazon brought the Echo Spot smart alarm clock back from the dead last year with a new design and improved speakers. In addition to being able to control smart home devices and respond to voice commands, the Echo Spot can also act as a Wi-Fi extender for those that have Eero systems. It went as low as $45 for Black Friday last year.

Samsung EVO Select microSD card (256GB) for $23 ($4 off): This Samsung card has been one of our recommended models for a long time. It's a no-frills microSD card that, while not the fastest, will be perfectly capable in most devices where you're just looking for simple, expanded storage.

Ring Pan-Tilt Indoor Cam $40 ($20 off): If you like the idea of being able to move the camera around to follow the action in your home, you may want to get a pan-and-tilt option like this one. We will again note that new Ring devices are on the way, but if you don’t have to have the latest thing and just want to see what your dog gets up to while you’re gone, you may want to snag this 33 percent discount.

Anker Soundcore Space A40 for $43 ($37 off with Prime): Our top pick for the best budget wireless earbuds, the Space A40 have surprisingly good ANC, good sound quality, a comfortable fit and multi-device connectivity.

JLab Go Air Pop+ for $17.49 ($12 off with Prime): JLab earbuds pop up in a few of our guides including the best running headphones and best budget buds. The Pop+ earbuds are smaller and lighter than the previous model, and the app’s preset EQ modes let you customize your sound. Total battery life with the case comes in at more than 35 hours.

This article originally appeared on Engadget at https://www.engadget.com/deals/the-59-best-amazon-prime-day-deals-under-50-from-anker-ring-lego-roku-and-others-120531690.html?src=rss

Prime Day Kindle deals include the Colorsoft for a record-low $200

Prime Day is usually a good opportunity to snag deals on Amazon's own product lines, and this event is no exception. Amazon is currently offering some noteworthy discounts on its collection of ereaders. The standout is the Kindle Colorsoft, which is on sale for $200. That's a $50 savings on the 16GB model and a record low price for this product.

The cost was one of the only real detractions we found in our review of Amazon's long-awaited color screen ereader, which has a bunch of nice features. The warm light of the screen is adjustable so that you can read easily in different lighting conditions, and there are no ads on the lock screen. If you're reading a lot of comics or manga, you'll likely appreciate both the color screen and the Colorsoft's pinch-to-zoom feature. Amazon says the Colorsoft can last up to eight weeks on a single battery charge, and it's waterproof in case you want to bring it to the beach or the pool (or if you just don't want to risk ruining it if you knock over your water bottle).

Colorsoft isn't the only Amazon ereader that's on sale for Prime Day. The standard Kindle model is currently available for $85, down from its usual $110 cost. You can also pick up a Kindle Paperwhite for $125, discounted from $160. Both of these options made our ranking of the best ereaders, with the Kindle winning our recommendation for an entry-level option and the Kindle Paperwhite impressing us as the best premium pick.

This article originally appeared on Engadget at https://www.engadget.com/deals/prime-day-kindle-deals-include-the-colorsoft-for-a-record-low-200-093010883.html?src=rss

The best Prime Day kitchen deals include our favorite Instant Pots, blenders and more, save up to 50 percent before the sale ends

There's just a handful of hours left in Amazon's October Prime Day sale. And if you're in the market for new kitchen gear to help out with holiday cooking, now's a good time to shop. We've tested plenty of helpful cooking gear here at Engadget and intriguingly, many of those items are now on sale. Many will require you to be a Prime member to get the full discount. But if you've already paid your dues, you can save on some of our recommended rice cookers, air fryers, blenders, mixers and more. Most of these deals are likely to go away once the sale ends, but in the meantime, here are the best Kitchen tech deals for Prime Day that you can still get. 

KitchenAid Artisan Series Stand Mixer for $379 ($121 off): There’s a reason this is so popular among home bakers and chefs. The Artisan KitchenAid is sort of the gold standard stand mixer, as we point out in our guide to the best kitchen tech. This isn’t an all-time low (it was $350 as recently as May), but matches the July Prime Day price.

Ninja Slushi for $300 ($50 off): We haven’t officially tested this one just yet, but given our love of both the Creami and the Creami Swirl, it’s a fair bet that this one will do good things with cold stuff too. This is the lowest price of the year so far.

Cosori 9-in-1 TurboBlaze Air Fryer for $90 ($30 off with Prime): This is the runner up pick in our air fryer buying guide. We appreciate the roomy basket and easy-to-use touchscreen. It’s missing the clear front window that our top pick from Instant has but, unlike that one, the Cosori has a release button on the basket which is a welcome safety feature.

Vitamix 2-Speed Immersion Blender for $90 ($40 off with Prime): For quick sauces and soups, we like this nifty two-speed hand blender from Vitamix, and said so in our guide to cheap kitchen gadgets. It even comes with a whisk for making your own whipped cream.

Ninja Dual Foodie Zone Air Fryer (DZ302) for $160 ($70 off): If you want to air fry two different things at the same time, this is the one to get. This is the same in specs, capacity and wattage as our top pick for a dual-zone air fryer, just with a different model number. It even has a feature that makes sure the two different foods are ready at the same time.

Vitamix 5-Speed Immersion Blender for $200 ($100 off with Prime): If you want a little extra oomph from your hand blender, grab this one. We named it the best counter top replacement model in our guide to the best immersion blenders. The 625 watt motor is more powerful than most and the blender head is intelligently designed to reduce suction and prevent scratches plus it fits inside a wide mouth mason jar.

Ninja Creami ice cream maker $180 ($50 off): This is one of our favorite pieces of kitchen tech and we called it a frozen fantasy-maker in our review. Note that the Creami dipped down to $160 last Black Friday but this matches the lowest price we've seen this year.  

Instant Pot Vortex Plus with Clear Cook for $80 ($20 off with Prime): This Vortex air fryer model is similar to our top airfryer pick, but is missing the Odor Ease feature. It still has the Clear Cook window that lets you keep an eye on your food as it crisps and the Vortex cooking tech heats up remarkably fast, with almost no pre-heating time.

Meater Pro wireless thermometer for $99 ($31 off with Prime): This was previously called the Meater 2 Plus, but the company changed the name. We gave it high praise in our review, and like the extended range, strong battery life, durability and precision.

Fellow Stagg EKG Pro Electric Gooseneck Kettle for $144 ($36 off with Prime): This is one of the appliances we recommend in our guide for tea gifts. I bought one based on that suggestion and have been impressed with this little kettle’s speed and good looks ever since.

Instant Pot Vortex Plus Air Fryer (4QT) for $65 ($65 off with Prime): Here’s a smaller version of our best overall air fryer. This one has a four-quart capacity, which is perfect for one person and small kitchens. And, like its larger sibling, pre-heats quickly thanks to a 1600-watt output. 

KitchenAid Variable Speed Corded Hand Blender for $55 ($15 off): We recommend the cordless version of this immersion blender in our guide to those appliances. This corded version has the same variable speed trigger which makes it easy to control your recipes. Note that this sold for $5 less as recently as May.

Breville Joule Turbo Sous Vide Machine for $200 ($50 off): This is the premium pick from our guide to sous vide machines. It has a powerful 1,100-watt heater and a Turbo mode that significantly reduces cooking times. But there are no built-in controls — you’ll have to use your phone and Breville’s free app to use it.

AeroPress Original for $30 ($10 off): We’re fans of AeroPress portable coffee makers and recommend the pricer Go Plus model in our guide to coffee gifts. If you don’t want to spend quite so much, grab the original model, which is even cheaper for Prime Day.

Breville InFizz Fusion beverage maker for $200 ($50 off): We called this fizz-maker the bubble master in our review. True, it’s pricier than rivals in the same space, but the upscale design — that actually looks good on a countertop — somewhat makes up for the price premium. We also appreciate the Fusion Cap that helps prevent messy eruptions when you’re bubbling up your drinks.

Hamilton Beach Digital Rice Cooker for $37 ($13 off with Prime): Our top pick for a budget rice cooker is great for small kitchens (but probably not for big families). We thought it outperformed other cookers that are four times the price, though it’s not the best for all-day warming of rice as the bottom bigs got a little overdone.

Cosori Air Fryer Pro Compact for $85 ($15 off with Prime): One of our concerns with the Cosori 9-in-1 was that it was a little on the wide side, taking up extra countertop space. The Pro Compact has a more space-saving design while still packing a five-quart basket.

Instant Pot 4QT Vortex mini air fryer for $55 ($35 off with Prime): This model’s four-quart capacity falls between our top Instant Pot air fryer pick and the budget model. It has the Clear Cook window feature, six presets and it comes in pink in addition to the standard white and black.

Instant Pot Duo Plus for $70 ($70 off with Prime): We named this the best multicooker in our guide to the best kitchen tech we’ve tested. It can cook a dizzying array of foods from basic beans and rice to homemade yogurt. We like this one because it’s simple to use, and has quick-cooking modes for soup, eggs and grains. There’s even a sous vide cooking function.

Breville Bambino Plus for $400 ($100 off): In our gift guide for coffee lovers, this espresso machine earned our respect for its compact size and the fact that it doesn’t cost a grand, like some machines do. Plus the controls are easy for beginners to learn but makes silky milkfoam for pro-level latte artists.

Breville Juice Fountain Plus for $120 ($30 off): This went as low as $110 back in January, but it’s still a decent discount on a high-powered juice extractor. We were won over by its impressive juicing abilities and despite how it looks, it's surprisingly easy to clean — as long as you do it right away.

Ninja 5.5-quart Air Fryer XL (AF150AMZ) for $130 ($50 off with Prime): This one earned an honorable mention in our guide to air fryers. It’s double the capacity of our budget pick and has a dehydrate preset. While we found the round basket a little cramped, we liked how the fryer’s vertical design saved counter space. Just note that this went as low as $90 in July.

Vitamix Explorian E310 Blender for $330 ($50 off): This isn’t the best deal we’ve seen this year — this Vitamix dropped to $300 as recently as May. But if you’re in the market for a blender that can turn the most recalcitrant nut into the creamiest butter, we think this won’t let you down.

This article originally appeared on Engadget at https://www.engadget.com/deals/the-best-prime-day-kitchen-deals-include-our-favorite-instant-pots-blenders-and-more-save-up-to-50-percent-before-the-sale-ends-193009680.html?src=rss

The best Prime Day gaming deals that are still available: Save on PS5 games, headsets, controllers and more

Among the many discounts included in Amazon’s October Prime Day sale are several price drops on video games and gaming gear. To make things a little less overwhelming, we've cut through the noise and rounded up the best Prime Day gaming deals that are still available below. Just remember that some of the offers in the "Prime Big Deal Days" event, as it's officially called, are exclusive to Prime subscribers, and that the sale itself ends at 3AM ET on October 9.

Elden Ring (PS5) for $30 ($20 off MSRP): You’ve probably heard about it by now, but the action-RPG Elden Ring is both challenging and darkly funny, with a world that runs incredibly deep and feels lived-in a way few games have. It’s unafraid to test your resolve, yet it always grants you the freedom to simply turn around and find another path forward.

Final Fantasy VII Rebirth (PS5) for $35 ($15 off): Engadget’s Mat Smith gave this grandiose action-RPG a favorable review last year. You need to have played its predecessor — and ideally, the original PS1 game — to get the most out of it, but it’s positively stuffed with things to do, and its combat system is still a tactical rush at its best.

Gran Turismo 7 for $30 ($40 off): Gran Turismo 7 is the PS5’s premier sim racer, and a love letter to automobiles as a whole. Like the rest of the GT series, it revels in the patience and precision required to figure out how a given car meshes with a given course. Learning the intricacies of each combination is both intense and rewarding, and there’s a singular style to it all that just doesn’t exist with most sports games.

Returnal for $30 ($70 off): Returnal is a third-person shooter roguelike that’s at once a technical showcase, a stiff challenge and an achingly beautiful reflection on the nature of grief. It is not for the faint of heart, but its bullet-hell battles are wonderfully fierce, and just about everything in it contributes to its overarching story. It’s also worth checking out if you’re eager to developer Housemarque’s next game, Saros, which seems to borrow many of the elements introduced here.

The Last of Us Part I for $30 ($40 off): The PS5 remake of Sony’s zombie drama is one of the most unnecessary remakes ever made, but if you’ve never played one of the earlier versions, this is the best way to rectify that. If you’re looking to play the (even moodier) sequel, the PS5 version of that one is similarly discounted.

God of War Ragnarok for $30 ($40 off): Ragnarok is another Sony sequel that’s more about increasing scope than radically reinventing itself, but its Norse world is beautifully varied and detailed, smashing baddies with a magic axe feels great, and the whole thing is excessive in the way you’d expect a God of War game to be without going overboard.

Horizon Forbidden West for $30 ($40 off): Engadget’s Jess Conditt called Horizon Forbidden West the “total package” in her review a few years back, praising its frenzied combat, gorgeous art direction and complex narrative. It still has one of the more distinctive post-apocalypses in gaming, blending robot beasts with stunning vistas. That helps paper over some less-than-inspired side content and bits of sluggish pacing.

Final Fantasy XVI (PS5) for $23 ($7 off): Final Fantasy XVI is a more straightforward action-RPG than something like Final Fantasy VII Rebirth: You don’t need to come in with prior knowledge of any other story, and its hack-and-slash combat is simple to pick up. It can get bogged down in pointless side quests, but its main concern is having you watch giant demigods melodramatically smack each other, and there’s nothing wrong with that.

Armored Core VI: Fires of Rubicon for $20 ($10 off): Armored Core VI is a big loud action game about building a mech and using it to blow up everything in sight. It rules. But it’s not mindless: Its many boss fights are genuine duels, and it’s deeply flexible in how it lets you tweak your death machine to tackle stages in different ways. This ties the best price we've seen for the PS5 version.

Metaphor: ReFantazio (Xbox) for $16 ($54 off): It’s about as subtle as you’d expect a game named “Metaphor” to be, but the latest from the minds behind Persona 5 is a fantasy JRPG through and through: bombastic, stylish and deeply earnest. (And long.) This deal represents a new low, though it only applies to the Xbox copy.

Madden NFL 26 for $37 ($33 off): It always feels like Madden could use a creative reset, but at the end of the day, it’s Madden, and it works fine enough if you just want to scratch the pro football game itch. This is the largest discount we’ve seen for the latest entry, and it applies to the PS5, Xbox and Switch 2 copies.

Xbox Game Pass Ultimate (3-month) for $57 ($33 off): It hasn’t exactly been a great stretch for Xbox lately, what with Microsoft jacking up console prices, laying off huge swaths of employees and massively hiking the cost of its Game Pass service to $30 per month. But if you aren’t looking to cancel your Game Pass subscription as a result, you can still grab three months of the top-end Ultimate tier for a little less than its old going rate. While the service itself may end up being too pricey in the long term, it’s still home to a wide range of games worth checking out, so this offer might be useful if you have some free time coming up and want to blast through a few titles you’ve been meaning to get around to.

Astro A50 X gaming headset for $315 ($75 off): The A50 X is an upgrade pick in our guide to the best gaming headsets. It should specifically appeal to those who own multiple gaming systems, as its base station lets you connect and swap between PC, PS5 and Xbox audio with the press of a button. It’s among the better-sounding wireless headsets we’ve tried as well, and its mic is fantastic. This deal isn’t an all-time low, but it’s the largest drop we’ve seen since February. The standard Astro A50 is also on sale for $237; that one works just as well if you only play on one device, but it lacks HDMI switching functionality.

8BitDo Ultimate 2 Wireless Controller for $48 ($12 off): The Ultimate 2 is a versatile wireless gamepad for Windows PCs and mobile devices. It can connect over Bluetooth, a wireless dongle or a USB cable, and its magnetic TMR joysticks should be far less susceptible to “joystick drift” than typical controllers. Those with large hands may find it a touch too small, but it’s built well, it comes with a handy charging dock and it gets a solid 20 or so hours of battery life. 8BitDo’s companion software includes a variety of useful customizations beyond that. This isn’t an all-time low, but it’s still a few bucks below the pad’s typical street price.

Corsair Scimitar RGB Elite MMO gaming mouse for $55 ($25 off): We recommend the Scimitar RGB Elite to MMO and MOBA players in our guide to the best gaming mice. It’s not the lightest or most technically advanced model, but it comes with 12 comfortable and easy-to-reach side buttons, which make it easier to pull off more complex actions in games like World of Warcraft or Final Fantasy XIV. We’ve seen it fall below $50 a few times before, but this deal matches the lowest price we’ve tracked since May. A newer wireless model called the Scimitar Elite Wireless SE is also on sale for a low of $80.

Razer Basilisk V3 gaming mouse for $30 ($40 off): We recommend the Basilisk V3 in our gaming mouse guide for those who don’t mind using a cable and prefer a more ergonomic right-handed shape. This is its lowest price to date. Note that Razer now sells a newer version with an improved sensor, but that one costs $49 more and isn’t a massive upgrade in real-world use.

Razer DeathAdder V3 HyperSpeed gaming mouse for $71 ($29 off): The wireless DeathAdder V3 HyperSpeed is another recommendation from our gaming mouse buying guide. For less than $100, it gets you a sturdy yet superlight design that weighs just 55 grams — making it easy to flick around in fast-paced games — and doesn’t have any annoying cutouts in its outer shell. Its contoured shape should fit most small- to medium-sized hands comfortably, and it performs reliably for competitive play. This deal is an all-time low.

Keychron Q3 Max mechanical keyboard for $195 ($35 off): The Keychron Q Max series is the top pick in our guide to the best mechanical keyboards, pairing an upscale (if heavy) aluminum case with a lovely typing experience and extensive customizability. This isn’t the lowest price we’ve ever seen for the tenkeyless model, but it’s a rare drop from the board’s typical street price. Other size layouts are discounted as well.

ASUS ROG Strix Scope II 96 Wireless mechanical keyboard for $151 ($59 off): We speak positively about this model in our guide to the best gaming keyboards. Its sturdy case, crisp keycaps and battery life all impress, while the thocky NX Snow switches in this model feel and sound delightful. Its companion software is a bit of a mess, and its 96 percent layout may feel a little cramped to some, but it’s a nice buy if you want a higher-class pre-built keyboard. This is the lowest price we've seen since March.

ASUS ROG Azoth mechanical keyboard for $155 ($120 off): It’s a couple years old at this point, but the ROG Azoth remains an exceptionally well-built mechanical keyboard for enthusiasts. Its gasket-mounted design and layers of foam give each key press a soft landing, while its pre-lubed switches feel nice and smooth. It even comes with a toolkit for manually lubing the switches down the road, and the PCB is hot-swappable if you ever want to switch things up. There’s a useful control knob and programmable OLED display for quickly adjusting settings and checking the battery level beyond that. ASUS' Armoury Crate software is still fairly sloppy, however. This deal comes within a couple bucks of the lowest price we've seen for a model with the linear NX Snow switches.

PNY microSD Express Card (128GB) for $38 ($7 off): We generally recommend getting at least 256GB of storage from your Switch 2 microSD card, since recent games can fill up that space pretty quickly. But if you only want a little bit extra, this is the lowest price we’ve seen for PNY’s 128GB model. Just note that we found this card to be the slowest one we’ve tested when it came to moving games to the card from the Switch’s internal storage.

Seagate Storage Expansion Card for Xbox Series X/S (2TB) for $190 ($170 off): It’s annoying, but the only way to fully add storage to an Xbox Series X/S is to use a proprietary expansion card. Seagate’s model is one of the very few examples of those, and this discount marks the lowest price we’ve seen for the 2TB variant in the past year. Yes, it’s still overpriced compared to a normal SSD, but any extra savings should be welcome.

Crucial X9 Pro (1TB) portable SSD for $75 ($26 off): If you’re looking to offload some games to external storage, we consider the Crucial X9 Pro the best portable SSD for most people, as it offers fast enough transfer speeds in a rugged and compact design. This isn’t the best price ever for the 1TB model but it matches the largest discount we’ve seen since April. Other size options are also on sale.

Crucial P310 (1TB) M.2 2230 SSD for $80 ($55 off): The P310 is a small-size SSD you can use to add storage to a handheld PC like the Steam Deck or ASUS ROG Ally. It uses cheaper QLC memory, not the faster and more durable TLC, but reviews say that it performs well anyway. This deal ties the best price we’ve seen for the 1TB version since April.

This article originally appeared on Engadget at https://www.engadget.com/deals/the-best-prime-day-gaming-deals-that-are-still-available-save-on-ps5-games-headsets-controllers-and-more-082623683.html?src=rss

The best Prime Day TV deals still available on day 2: Take up to $500 off sets from Samsung, LG, Sony and more

Amazon’s newest October Prime Day sale is into its second and final day, but a number of highly-rated TVs from LG, Samsung, Sony and others remain discounted for the occasion. If you can’t wait until Black Friday to upgrade, we’ve rounded up the best Prime Day TV deals that are still available below. We’ve also thrown in a few discounts on streaming players we like. Just keep in mind that you may need to be a Prime member to see some of the discounts.

TCL QM7K 55-inch Mini-LED 4K TV for $570 ($330 off MSRP): If you’re willing to stretch your budget a little further, the TCL QM7K is a fairly comprehensive step up, with noticeably improved contrast, brightness and color volume. It has a 144Hz refresh rate with 288Hz support at 1080p, too, though it’s still limited to two HDMI 2.1 ports. (As with the QM6K, however, neither of those is an eARC port, so hooking up a soundbar won’t block a game console if you have multiple systems.) This discount represents a new low, beating the previous best mark we've seen by roughly $30.

Hisense U8QG 65-inch Mini-LED 4K TV for $998 ($500 off): Several reviews suggest that the Hisense U8QG ticks most of the requisite boxes for a LCD TV in 2025: robust local dimming and mini-LED backlighting, exceptionally high brightness, vibrant quantum-dot colors, a fast refresh rate (165Hz in this case), support for the major HDR formats and so on. It’s a higher-end option than something like the TCL QM6K or QM7K with superior brightness and contrast, though it still falls short of a good OLED TV when it comes to the latter. Like most LCD panels, it’ll also look a bit washed out if you view it from an angle. It has three HDMI 2.1 ports, which is one fewer than many other TVs in this price range, though it uniquely includes a USB-C video input if you want to hook up a gaming laptop or Nintendo Switch. (Just note that you won’t get VRR or HDR when using that.) You’d mainly get it over an OLED TV if you’re willing to trade some picture quality for something better-suited in a bright room. This deal on the 65-inch model matches the best price we've tracked.

Samsung S90F 55-inch QD-OLED 4K TV for $1,100 ($498 off): The Samsung S90F is an upper-tier model with a QD-OLED panel, which blends the usual perks of a quality OLED set — near-perfect contrast, wide viewing angles, clear motion, low input lag — with a layer of quantum dots. This helps it produce a wider gamut of more vivid colors compared to traditional WOLED TVs. It also comes with four HDMI 2.1 ports and has a fast refresh rate of 144Hz. It doesn’t support Dolby Vision HDR, however, and reviews we trust say that the LG C5, a competing WOLED model, retains darker black levels in a bright room. This deal marks a new low for the 55-inch model, while the 65-inch and 77-inch versions are also at all-time lows of $1,598 and $2,298, respectively. Just make sure you only buy the 55-, 65- or 77-inch model, as every other size in the US uses a lesser WOLED panel. Shady, we know.

LG C5 65-inch OLED 4K TV for $1,373 ($1,309 off): The LG C5 can’t produce the same bold colors as a QD-OLED display like the Samsung S90F, but reviews almost universally agree that it’s an exceptional OLED TV otherwise. It should get brighter with non-HDR content, and as noted above it should produce deeper blacks in well-lit environments. It also has just about all the essential gaming features, plus it supports the popular Dolby Vision HDR format (but not HDR10+). If you need that, or if you want an OLED set in this price range for a bright-ish room, it’s well worth a look. This is nearly an all-time low for the 65-inch model, beating its typical street price by about $125. You should see the full discount at checkout. Other sizes are also on sale, but note that the 42- and 48-inch models can’t get as bright as the larger versions.

LG B5 55-inch OLED 4K TV for $997 ($100 off): The B5 is LG’s entry-level OLED TV for 2025, and as such it’s a level below the C5 in terms of brightness and color performance. It’s technically limited to a 120Hz refresh rate instead of 144Hz as well, though that isn’t a huge deal right now unless you plan on hooking up a gaming PC. If anything, last year’s LG C4 — which isn’t seriously discounted as of this writing — is a better value for most on the whole. But if you just want to save cash, the B5 still provides most of the core benefits of an OLED display at a lower price. This is a new all-time low for the 55-inch variant.

Samsung S95F 55-inch QD-OLED 4K TV for $1,998 ($200 off): If you’re willing to pay for a top-of-the-line OLED TV, the Samsung S95F should fit the bill. Reviews around the web praise it for being especially bright for an OLED TV while retaining the bold colors and superb contrast you’d want from a high-end QD-OLED panel. That brightness combined with the screen’s matte finish means it’s particularly adept at fending off glare, so it’ll be effective in either a dark or bright room. It’s also loaded with gaming features, including a 165Hz refresh rate. That said, the matte coating means black levels won’t be as deep in a well-lit environment, and there’s still no Dolby Vision support. This is the lowest price we’ve seen for the 55-inch model.

LG G5 55-inch OLED 4K TV for $1,747 ($753 off): The LG G5 competes with the Samsung S95F in the top end of the OLED TV market. Most reviews say it can get even brighter than Samsung’s model, it supports Dolby Vision and its lack of a matte coating means it won’t lose its inky black levels in a bright room. That said, having a glossy finish also means that it’s more susceptible to direct reflections. And while its picture is a level above most other WOLED TVs, it isn’t quite on par with the S95F when it comes to color volume. Still, if you’re mainly going to watch things in the dark, it might be the better buy. This is a new low for the 55-inch variant.

Sony Bravia 8 II 65-inch QD-OLED 4K TV for $2,798 ($702 off): It’s certainly not cheap, but the Sony Bravia 8 II has earned plaudits for its excellent image processing, upscaling and overall accuracy alongside the expected color, contrast and motion benefits of its QD-OLED display. This should help it make lots of movies and shows look closer to their original intent. It also uses the handy Google TV interface. This deal marks the best price to date for the 65-inch version. That said, if you can’t stomach the high price, other reviews note that the older Sony A95L offers similar performance a bit less, while more recent competitors like the LG G5 and Samsung S95F can get noticeably brighter (even if they’re not always as accurate). Those two should be better for gaming as well, as the Bravia 8 II only has two HDMI 2.1 ports — one of which is an eARC port for soundbars — and its input lag is slightly higher.

Sony Bravia 9 75-inch Mini-LED 4K TV for $2,798 ($702 off): The Bravia 9 is Sony’s flagship mini-LED TV. It’s pricier than many OLED TVs, but most reviews say that it produces better contrast and black levels than the vast majority of non-OLED sets, with minimal light bloom around bright objects onscreen. So it’s still a strong performer in a dark room. Like the best LCD TVs, it can also get super bright, and it delivers the excellent upscaling and image processing that high-end Sony TVs are known for, so it should make old DVDs and lower-quality streams look their best. That said, the top OLED TVs still have it beat when it comes to contrast, color volume and viewing angles. It’s also not the best choice for gaming, since it’s limited to two HDMI 2.1 ports and has slightly higher input lag than other models. But if money is no object and you don’t want to go OLED, it should satisfy. This discount matches the lowest price we’ve seen for the 75-inch version.

Roku Streaming Stick 4K for $30 ($20 off): The Streaming Stick 4K is worth considering if you prefer a stick-style streamer that plugs directly into your TV, or if you’re partial to Roku’s app-centric interface, which many find simpler to navigate than the content-heavy UIs pushed by Google and Amazon. It supports Apple AirPlay and the major HDR formats, and its performance remains quick enough for most. You’ll have to deal with some ads, though, and no Roku player supports the Twitch app. This deal is $5 more than the device’s all-time low but ties the best price we’ve seen in several years.

Roku Streaming Stick Plus for $24 ($16 off): The Streaming Stick Plus is cheaper alternative to the Streaming Stick 4K with no Dolby Vision support and no long-range Wi-Fi extender built in. The latter means it may be less reliable if you don’t get a consistent connection in your TV’s room. (Both sticks are limited to Wi-Fi 5, though.) That said, this model can typically be powered straight from a TV’s USB port instead of requiring a separate power supply. If you can live with the sacrifices, it may not be worth paying extra. This deal represents a new all-time low.

Roku Ultra for $69 ($31 off): You’d buy the Roku Ultra if you want the Roku interface in a set-top box design with built-in Ethernet and USB ports. Unlike the company’s streaming sticks, it comes bundled with a rechargeable remote that supports voice controls, a lost remote finder tool and backlit buttons. (You can buy that separately, though.) This latest model also has a faster processor and Wi-Fi 6 support. This deal ties an all-time low.

Amazon Fire TV Stick 4K for $25 ($25 off): The standard Amazon Fire TV Stick 4K offers the same core experience as the pricier Fire TV Stick 4K Max, only it comes with a slightly slower processor, half the storage (8GB) and Wi-Fi 6 instead of Wi-Fi 6E. For most people just looking for a casual streamer on the cheap, those shouldn’t be huge losses. This model is also more powerful than the just-announced Fire TV 4K Select, though its Fire OS interface can still be messy and ad-heavy, with special emphasis on Amazon’s own services. This deal is $3 more than the stick’s all-time low, though it matches the best price we’ve seen since Black Friday last year.

Amazon Fire TV Stick HD for $18 ($17 off): The Fire TV Stick HD is the budget pick in our guide to the best streaming devices. It can only stream up to 1080p, and it can run a bit choppier than the 4K models since it has a slower chipset and half the RAM (1GB). The usual issues with the Fire TV interface still apply here too. But if you just want to add streaming apps to an aging TV or basic monitor for as little cash as possible, it should get the job done. This discount ties the device's lowest price to date.

This article originally appeared on Engadget at https://www.engadget.com/deals/the-best-prime-day-tv-deals-still-available-on-day-2-take-up-to-500-off-sets-from-samsung-lg-sony-and-more-180051817.html?src=rss

The best Amazon Prime Day deals on Kindles, Echo speakers, Fire TV devices and more for Day 2

Amazon’s own gadgets — Echo speakers, Fire tablets, Kindles and the like — are at the top of the list of tech on sale during October Prime Day. While there are some (Echos, Kindles) that we like more than others (Fire tablets), there’s no question that you’ll get the best discount on all Amazon tech during Prime Day. The online retail giant typically discounts all of its in-house-made gear for Prime Day, and this year is no different. Here, we’ve collected all of the best October Prime Day deals on Amazon gear that you can still get today before the sale ends tonight.

Kindle Kids for $95 ($35 off): This is the same device as the base Kindle, but it becomes more kid-friendly thanks to the included cover, two-year warranty and the included year of Amazon Kids+, which gives children ages 3-12 access to hundreds of appropriate ebooks and audiobooks. Just be sure to take note when you activate that subscription because it will renew after one year at the standard $6/month rate.

Kindle Paperwhite for $125 ($35 off): The latest version of the Paperwhite has a seven-inch display, thinner bezels, an adjustable warm light, speedier page turns and a battery that can last up to 12 weeks on a single charge. This model is also IPX8 waterproof and has built-in Audible integration.

Kindle Colorsoft for $200 ($50 off): Amazon's only color e-reader has a seven-inch, high-contrast display, an auto-adjusting front light, a color highlighting feature and an eight-week battery life.

Kindle Scribe for $300 ($100 off): The Scribe is one of the best E-Ink tablets you can buy at the moment, and certainly the top pick if you want a writable table that also excels as an ereader. It provides a great reading and writing experience, thanks in part to its ability to access the entire Kindle ebook library, and it has handy Google Drive, Microsoft OneDrive and Dropbox integration.

Echo Pop speaker for $25 (38 percent off): One of the newer Echo devices available, the Pop it sports a 1.95-inch front-facing speaker and a physical mic mute switch for extra privacy. The Pop also has built-in eero compatibility, so it can extend the area of your home Wi-Fi network if you already have an eero router system.

Echo Dot speaker for $35 (30 percent off): One of the smallest Echo speakers, this version of the Dot has improved audio and a compact design that will fit almost anywhere. You'll control it mostly with Alexa voice commands, but there are a few onboard buttons, including a mic-off button for when you need more privacy.

Echo Show 5 for $55 (39 percent off): This model is one of our favorite smart displays thanks to its compact design, ambient light sensor and sunrise alarm feature, all of which make it an excellent smart alarm clock. Amazon improved the speaker quality on this latest model, which gives sound deeper bass and clearer vocals.

Echo Show 8 for $100 (33 percent off): This is our current top pick for the best smart display with Amazon’s Alexa thanks in part to its 8-inch touchscreen, 13MP camera that supports auto-framing for better video chats and its built-in Zigbee smart home hub. The 2023 model supports Visual ID, which will show personalized information on the device’s display depending on who’s using it, and video streaming from Netflix, Hulu, Prime Video and other services.

Fire TV Stick 4K for $25 (50 percent off): This is the cheapest Fire TV Stick you can get to stream 4K content, plus it has support for Wi-Fi 6 and Dolby Vision and Atmos. With its live picture-in-picture feature, you can view security camera feeds right on your TV while you’re watching your favorite show or movie.

Fire TV Stick 4K Max for $40 (33 percent off): In addition to 4K HDR streaming with Dolby Vision and Atmos support, the 4K Max dongle includes Wi-Fi 6E connectivity, 16GB of built-in storage and live picture-in-picture capabilities. It also supports the Fire TV “ambient experience,” which lets you display photos and images on your TV screen when you’re not actively watching something.

Fire TV Cube streaming box for $100 (29 percent off): This model will provide the best performance of any Fire TV streaming device, and it supports 4K HDR content, Dolby Vision and Atmos and an enhanced version of the Alexa Voice Remote. Along with live picture-in-picture view and the Fire TV ambient experience, you can also hardware other devices to the Fire TV Cube including a cable box or a game console.

Fire HD 8 tablet for $55 (45 percent off): This is Amazon's most bare-bones tablet, featuring an eight-inch HD touchscreen, hexa-core processor and 13 hours of battery life. The improvements in the screen quality alone from the old-school Fire 7 tablet make it a better buy for most people, and this slab would make a good couch device for general web browsing, email checking, online shopping and more.

Fire Max 11 tablet for $140 (39 percent off): Amazon’s most powerful tablet, the Fire Max 11 sports an 11-inch 2,000 x 1,200 touchscreen, an octa-core processor, up to 128GB of storage and 14 hours of battery life. It also works with a number of optional accessories, including a stylus and keyboard case.

Fire HD 10 Kids tablet for $105 (45 percent off): This slab is designed for kids aged three to seven, with full parental controls plus one year of Amazon Kids+ for free with the tablet purchase. This model has a 10-inch FHD touchscreen, an octa-core processor and 13 hours of battery life, plus it comes with a two-year warranty and a protective case.

Fire HD 10 Kids Pro tablet for $105 (45 percent off): This model is designed for kids aged six to 12 and comes with a slimmer protective case, a two-year warranty and one year of access to Amazon Kids+. Otherwise, you get a very similar experience here that you would with the non-Pro version, including parental controls, a 10-inch touchscreen, solid performance and a 13-hour battery life.

This article originally appeared on Engadget at https://www.engadget.com/deals/the-best-amazon-prime-day-deals-on-kindles-echo-speakers-fire-tv-devices-and-more-for-day-2-081210482.html?src=rss

Get three months of Audible for only $3 with this Prime Day deal

The traditional Amazon Prime Day Audible sale has returned for October Prime Day. Audiobook fans can get three months of Audible for just $3, or $1 per month for the first three months. Once the three-month initial period is over, though, the subscription will auto-renew at $14.95 per month.

Audible features thousands of titles in its catalog, including podcasts and Audible Originals. Subscribers will also get to choose one audiobook each month to keep in their collection for free, including best-sellers or new releases. Amazon Prime members will receive two credits the first month of their trial.

Amazon has been bringing Prime Day back in the fall for a few years now, and this year it returns October 7 and 8. Great deals tend to start rolling out in the days ahead of the event and this year is no exception. There are already sales on Apple devices, smart doorbells and most importantly, Lego sets.

If you're a book lover but don't have the time to sit down and read a hard copy, or you just prefer listening to the latest novel while on the go, then take advantage of this sale. It's a limited-time offer and will only be available through December 16.

This article originally appeared on Engadget at https://www.engadget.com/deals/get-three-months-of-audible-for-only-3-with-this-prime-day-deal-090052863.html?src=rss

We found the best Prime Day Anker deals on power banks, wireless chargers and other accessories

You may not be looking to spend big on tech this October Prime Day, but it's still a good idea to look for tech essentials during the shopping event while you can get some at good discounts. Anker makes some of our favorite charging gear and I always end up picking up an accessory or two during Prime Day to ensure I have what I need when I need it most, and I feel better knowing I didn't spend full price on it.

For example, in sales past, I picked up a couple of extra USB-C charging cables so I could keep one in my carry-on luggage so I always have one when I travel. My partner will likely be upgrading to an iPhone 17 this year, so we'll have to get a few more USB-C cables now that Lightning is officially banished from our home. Also, every year it seems I need yet another surge protector, so even though I picked one up the year before — but one can never have too many. Here, we've collected all of the best October Prime Day deals on Anker devices and other charging gear we could find, and we'll update this post as the event goes on with the latest offerings.

Power banks are not as straightforward as you might think. They come in all shapes, sizes and capacities and can have extra features like magnetic alignment, built-in kickstands, extra ports and more.

It's worth considering how you'll use a power bank before you decide on the right one to buy. Smartphones don’t need huge-capacity bricks to power up a couple of times over; a 5K or 10K portable charger should be plenty if that’s all you’re looking to support. If you want a more versatile accessory that can charge a tablet, laptop or gaming handheld, consider a brick with a higher capacity — and more ports so you can charge multiple devices simultaneously.

A good wireless charger can lighten your cable load. While wired charging remains faster and more efficient, wireless chargers can clean up your space by eliminating a few of those cables that constantly trip you up.

We recommend thinking about where you'll use a wireless charger before buying one. Those outfitting a home office with new tech may want a wireless charging stand that puts their phone in an upright position that’s easier to see while it’s powering up, while those who want a wireless charger for their nightstand might prefer a lay-flat design or a power station that can charge a smartphone, smartwatch and pair of earbuds all at once.

Plenty of other charging gear is on sale for Prime Day. It’s never a bad idea to pick up a few 30W USB-C adapters so you always have what you need to reliably power up your phone. Same goes for extra USB-C (or USB-A) cables that can live in your car, in your office at work or by the couch.

This article originally appeared on Engadget at https://www.engadget.com/deals/we-found-the-best-prime-day-anker-deals-on-power-banks-wireless-chargers-and-other-accessories-164536745.html?src=rss

The best VPN deals: Get up to 87 percent off ProtonVPN, ExpressVPN, Surfshark and more

A virtual private network (VPN) can come in handy in lots of ways every day, whether you're using one to stream foreign TV shows or keeping yourself anonymous online so advertisers can't track you. But while we strongly recommend using a VPN, it pays to do some research before investing in one. Pricing can be opaque for these services, but there are great deals to be had.

VPN provides often provide deep discounts to those willing to sign up for one or two years at a time. Though you're on the hook for the full charge up front, you're actually paying less per month over time. This way, VPN providers boost their subscriber numbers, and you get heavy price cuts on some of our favorite services.

Most of the deals we highlight below follow that pattern, so make sure you're comfortable with a longer commitment before you take the plunge. If you've been thinking about subscribing to a VPN service, read on for the best VPN deals we could find right now.

NordVPN — $83.43 for a two-year subscription with three months free (77 percent off): NordVPN gets the most important parts of a VPN right. It's fast, it doesn't leak any of your data and it's great at changing your virtual location. I noted in my NordVPN review that it always connects quickly and includes a support page that makes it easy to get live help. Although I'm sad to see it shutting down Meshnet, NordVPN still includes a lot of cool features, like servers that instantly connect you to Tor. This deal gives you 77 percent off the two-year plan, which also comes with three extra months — but there's no expiration date, so you have a little time for comparison shopping.

ExpressVPN Basic — $97.72 for a two-year subscription with four months free (73 percent off): This is one of the best VPNs, especially for new users, who will find its apps and website headache-free on all platforms. In tests for my ExpressVPN review, it dropped my download speeds by less than 7 percent and successfully changed my virtual location 14 out of 15 times. In short, it's an all-around excellent service that only suffers from being a little overpriced — which is why I'm so excited whenever I find it offering a decent deal. This deal, which gets you 28 months of ExpressVPN service, represents a 73 percent savings. It's the lowest I've seen ExpressVPN go in some time, though like NordVPN, it's not on a ticking clock.

ExpressVPN Advanced — $125.72 for a two-year subscription with four months free (67 percent off): ExpressVPN recently split its pricing into multiple tiers, but they all still come with similar discounts for going long. In addition to top-tier VPN service, advanced users get two additional simultaneous connections (for a total of 12), the ExpressVPN Keys password manager, advanced ad and tracker blocking, ID protection features and a 50 percent discount on an AirCove router.

Surfshark Starter — $53.73 for a two-year subscription with three months free (87 percent off): This is the "basic" level of Surfshark, but it includes the entire VPN; everything on Surfshark One is an extra perk. With this subscription, you'll get some of the most envelope-pushing features in the VPN world right now. Surfshark has a more closely connected server network than most VPNs, so it can rotate your IP constantly to help you evade detection — it even lets you choose your own entry and exit nodes for a double-hop connection. That all comes with a near-invisible impact on download speeds. With this year-round deal, you can save 87 percent on 27 months of Surfshark.

Surfshark Starter+ — $59.13 for a two-year subscription with three months free (87 percent off): If you want some of the extra features of the Surfshark suite but aren't interested in jumping all the way to Surfshark One, try this intermediate tier instead. Starter+ includes Alternative ID, which you can use to mask your details when you sign up for online accounts, and Surfshark Search, a private search engine with no ads or activity tracking. This is another year-round deal that works out to an 86 percent discount.

Surfshark One — $67.23 for a two-year subscription with three months free (86 percent off): A VPN is great, but it's not enough to protect your data all on its own. Surfshark One adds several apps that boost your security beyond just VPN service, including Surfshark Antivirus (scans devices and downloads for malware) and Surfshark Alert (alerts you whenever your sensitive information shows up in a data breach), plus Surfshark Search and Alternative ID from the previous tier. This evergreen deal gives you 86 percent off all those features. If you bump up to Surfshark One+, you'll also get data removal through Incogni, but the price jumps enough that it's not quite worthwhile in my eyes.

CyberGhost — $56.94 for a two-year subscription with two months free (83 percent off): CyberGhost has some of the best automation you'll see on any VPN. With its Smart Rules system, you can determine how its apps respond to different types of Wi-Fi networks, with exceptions for specific networks you know by name. Typically, you can set it to auto-connect, disconnect or send you a message asking what to do. CyberGhost's other best feature is its streaming servers — while it's not totally clear what it does to optimize them, I've found both better video quality and more consistent unblocking when I use them on streaming sites. Currently, you can get 26 months of CyberGhost for 83 percent off the usual price.

Private Internet Access — $79 for a three-year subscription with three months free (83 percent off): It's a bit hard to find (the link at the start of this paragraph includes the coupon), but Private Internet Access (PIA) is giving out the best available price right now on a VPN I'd recommend using. With this deal, you can get 39 months of PIA for a little bit over $2 per month — an 83 percent discount on its monthly price. Despite being so cheap, PIA almost never comes off as a budget VPN, coming with its own DNS servers, a built-in ad blocker and automation powers to rival CyberGhost. However, internet speeds can fluctuate while you're connected.

hide.me — $69.95 for a two-year subscription with two months free (73 percent off): Hide.me is an excellent free VPN — in fact, it's my favorite on the market, even with EventVPN and the free version of Proton VPN as competition. However, if you do want to upgrade to its paid plan, the two-year subscription offers great savings. Hide.me works well as a no-frills beginner VPN, with apps and a server network it should frankly be charging more for.

Like I said in the intro, practically every VPN heavily discounts its long-term subscriptions the whole year round. The only noteworthy exception is Mullvad, the Costco hot dog of VPNs (that's a compliment, to be clear). When there's constantly a huge discount going on, it can be hard to tell when you're actually getting a good deal. The best way to squeeze out more savings is to look for seasonal deals, student discounts or exclusive sales like Proton VPN's coupon for Engadget readers.

One trick VPNs often use is to add extra months onto an introductory deal, pushing the average monthly price even lower. When it comes time to renew, you usually can't get these extra months again. You often can't even renew for the same basic period of time — for example, you may only be able to renew a two-year subscription for one year. If you're planning to hold onto a VPN indefinitely, check the fine print to see how much it will cost per month after the first renewal, and ensure that fits into your budget.

Follow @EngadgetDeals on X for the latest tech deals and buying advice.

This article originally appeared on Engadget at https://www.engadget.com/deals/best-vpn-deals-120056041.html?src=rss

The best iPad for 2025: How to pick the best Apple tablet for you

We’ve long considered Apple’s iPads to be the best tablets on the market, but determining exactly which model you should buy isn’t always straightforward. Do you just want a big screen for streaming and web browsing? Do you want to use it like a pseudo-laptop? Do you care about Apple Intelligence at all? If you’re not sure, allow us to help. We’ve tested every iPad available today and broken down which ones should best fit your needs below.

iPad mini (2024) review photos
The top edge of the iPad mini.
Photo by Nathan Ingraham / Engadget

Much like we do for our guide to the best tablets overall, we spend several days with each iPad to see how they feel and perform with different tasks: watching videos, web browsing, playing both casual and graphically intense games, editing 4K photos and video, running multiple apps side-by-side, making FaceTime calls and the like. To better measure performance specifically, we use benchmarking tests like Geekbench 6, 3DMark and GFXBench Metal, plus we measure how long it takes for each tablet to boot up and open various apps. We also check how well each tablet holds up long-term, whether it’s with a review unit provided by Apple or an iPad model that’s owned by a member of the Engadget staff.

To help compare the color performance and brightness of the displays, we play the same videos on different iPads, side-by-side, at equal brightness levels. We use each tablet in direct sunlight outdoors to see how well they hold up to glare, and we play a handful of the same musical tracks to evaluate speaker performance. For battery life, we keep track of how long each tablet generally lasts before it needs a recharge, but we also play a 1080p movie on a loop at roughly 70 percent brightness with power-sapping background processes off. We also test each device with an Apple Pencil and note how responsive the stylus feels. Finally, we carefully pore over spec sheets and software updates to keep track of which features are available on certain iPads but not others.

A pink 11-inch Apple iPad rests on top of a silver 13-inch iPad Air. Both tablets are face down on a gray carpet with beige and white streaks.
The iPad (A16) on top of an 13-inch iPad Air.
Jeff Dunn for Engadget

Apple released the latest update to its iPad operating system, iPadOS 26, in September. The update is a fairly significant overhaul, one that brings iPadOS closer to macOS than ever before. New features include the ability to open more windows simultaneously and resize or tile them more freely; a Mac-style Menu bar; a dedicated Preview app; an upgraded Files app; an improved ability to export or download large files in the background; an Exposé view that shows all open windows; a pointier cursor and the option to add folders to the Dock. It also uses the new “liquid glass” design language that Apple is rolling out across all of its platforms in 2025.

That said, it completely removed the “slide over” and “split view” modes found in previous versions of iPadOS, which can make quickly viewing multiple apps at once a little more cumbersome. (Though the former will now return in an upcoming update.) Notably, most of these features are available across Apple’s tablet lineup, from the iPad Pro to the entry-level iPad. You can find the full list of compatible devices at the bottom of Apple’s overview page.

If history is any indication, expect Apple to update your iPad to the latest version of iPadOS for at least five years, if not longer. The current iPadOS 26 update, for example, is available on iPad Pro models dating back to 2018 and other iPads dating back to 2019. How long your iPad’s hardware will last depends on which model you buy and how well you maintain it. (If you’re particularly clumsy, consider an iPad case.) A more powerful iPad Pro will feel fast for a longer time than an entry-level iPad, but each model should remain at least serviceable until Apple stops updating it, at minimum.

Compared to the standard iPad, the iPad Air runs on a stronger M3 chip (instead of the A16 Bionic) and has 2GB more RAM (8GB total). Both come with 128GB of storage by default. The Air is also available in two sizes, 11 and 13 inches, whereas the 11th-gen iPad doesn't offer the larger screen option. The M-series SoC gives the Air better long-term performance prospects, plus access to certain iPadOS features such as Apple Intelligence. Its display supports a wider P3 color gamut, has an antireflective coating and is fully laminated. The latter means there’s no “air gap” between the display and the glass covering it, so it feels more like you’re directly touching what’s on screen instead of interacting with an image below the glass. The Air also works with the newer Pencil Pro stylus and more comfortable Magic Keyboards, and its USB-C port supports faster data transfer speeds. It technically supports faster Wi-Fi 6E, too, while the lower-cost iPad uses Wi-Fi 6.

Starting at $349, the 11th-gen iPad is $250 less expensive than the iPad Air. It has a similarly elegant design with flat edges, thin bezels, USB-C port, and a Touch ID reader. Battery life is rated at the same 10 hours, and both devices have their front-facing camera on their long edge, which is a more natural position for video calls. The cheaper iPad works with the first-gen and USB-C Apple Pencils – which are more convoluted to charge – and a unique keyboard accessory called the Magic Keyboard Folio.

A pink Apple iPad (A16) rests on the flat arm rest of a light brown leather chair, with its bottom edge facing the camera, showing off the device's thin profile along with its speaker grilles and USB-C port.
Jeff Dunn for Engadget

The operating system, duh. But to give a few more specifics: Android devices are available from more manufacturers and cover a wider price range. You won’t see an $80 iPad anytime soon. Android is also more malleable in that you can easily sideload apps from places beyond Google’s official app store and more extensively customize the look of the OS (though the former may no longer be an option in the coming months). Several Android tablets still have features like a headphone jack or a microSD slot for adding storage, too, though those are getting rarer.

But we tend to recommend Apple tablets to those who have no allegiance either way. iPad apps are still a bit more likely to be designed specifically for larger screens, rather than looking like blown-up phone software, and Apple is just about peerless when it comes to long-term software support. Every new iPad hits a certain baseline of hardware quality and performance — none of them feel cheap, and all of them are fast enough for most needs. Plus, you’ll get the most out of an iPad if you use other Apple devices.

This is a loaded question, since laptop workflows differ from person to person. If you mostly use a notebook for browsing the web, watching videos or writing emails and word docs, then sure, you can get along just fine with an iPad and the right iPad accessories. It’ll be easier to carry around, the battery life is great and having the touchscreen and stylus support is handy (though many Windows users have that regardless). Even beyond the basics, plenty of media editors, graphic designers and digital artists have shown they can get things done on an iPad.

Broadly speaking, though, a laptop OS tends to be more flexible when it comes to file management, multitasking, coding or other “heavy” tasks. The recent iPadOS 26 update does close the gap a bit, though it’s still not quite as fluid. Safari on the iPad isn’t fully on par with desktop browsers either. So the answer really depends on you.

As we note in our screenshot how-to guide, you can take a screenshot on your iPad by pressing the top button and either volume button at the same time. If you have an older iPad with a Home button, simultaneously press the top button and the Home button instead.

October 2025: We’ve made a few edits to reflect the full release of iPadOS 26 and made sure our recommendations are still accurate.

August 2025: We've taken another sweep to ensure our picks are still accurate and added a few more notes to our FAQ section.

June 2025: We’ve made a few minor edits to reflect the announcement of Apple’s latest iPadOS update, which we detail above.

May 2025: We’ve lightly edited this guide to ensure all details and links are still correct. We’re also keeping an eye on how the Trump administration’s tariff policy affects the pricing and stock of the iPad lineup (and every other tech category). All of our picks are still available at normal prices today, but we’ll update this guide if that changes.

March 2025: We've reviewed the iPad (A16) and named it our new budget pick, removing the discontinued 10th-gen iPad in the process. 

March 2025: The recently-launched iPad Air M3 has replaced its predecessor as our top overall recommendation. We’ve also made a note regarding the new iPad (A16), which we plan to test in the near future and expect to become our new budget pick. We’ve made a handful of edits elsewhere in the guide to reflect Apple’s latest hardware.

January 2025: We’ve lightly edited this guide for clarity. Our recommendations remain the same.

October 2024: We've updated our guide to include the new iPad mini 7.

June 2024: We’ve touched up this guide to reflect some of the new iPadOS features Apple announced at WWDC, though our picks remain the same.

Nathan Ingraham contributed to this report.

This article originally appeared on Engadget at https://www.engadget.com/mobile/tablets/best-ipads-how-to-pick-the-best-apple-tablet-for-you-150054066.html?src=rss

Apple explains how it will comply with App Store age verification requirements in Texas

Earlier this year,Texas passed a law requiring app stores to verify the ages of their users. Now, Apple has shared more about how it plans to comply with requirements, which are slated to go into effect next year.

Beginning January 1, 2026, people in Texas creating new Apple accounts will need to verify that they are over the age of 18, Apple said. And anyone under 18 will be required to link their account to a parent or guardian's via the company's Family Sharing settings. Parents will then be prompted to approve all of their child's downloads, in-app purchases and other transactions. 

While Apple didn't explain exactly how it will conduct age verification, the company noted that developers will also need to make changes in order to comply with the Texas law. The company is working on new developer tools so app makers can implement parental consent requirements and other age-restricted features. 

The Declared Age Range API is available to implement now, and will be updated in the coming months to provide the required age categories for new account users in Texas. And new APIs launching later this year will enable developers, when they determine a significant change is made to their app, to invoke a system experience to allow the user to request that parental consent be re-obtained. Additionally, parents will be able to revoke consent for a minor continuing to use an app. More details, including additional technical documentation, will be released later this fall.

Apple had opposed the law and CEO Tim Cook personally lobbied Texas Governor Greg Abbott to veto the measure. In its latest update, the company made clear that it still isn't enthusiastic about Texas' approach. "While we share the goal of strengthening kids’ online safety, we are concerned that SB2420 impacts the privacy of users by requiring the collection of sensitive, personally identifiable information to download any app, even if a user simply wants to check the weather or sports scores," Apple said in its note to developers. 

Though Texas' age verification law for app stores  will be the first to take, it isn't the only state to implement such requirements. Utah and Louisiana have also passed laws requiring app stores to conduct age verification checks. Those measures will also take effect in 2026.


This article originally appeared on Engadget at https://www.engadget.com/big-tech/apple-explains-how-it-will-comply-with-app-store-age-verification-requirements-in-texas-185934469.html?src=rss

Tag Heuer made a smartwatch with New Balance

Tag Heuer has announced its latest luxury smartwatch, the Connected Calibre E5, and it comes complete with a partnership with sneaker maker New Balance on a particularly sporty version. The biggest selling point here is likely the design. This is a snazzy-looking watch, with a bright purple and green color scheme that is reminiscent of Unit-01 from Evangelion.

The exterior is coated in Grade 2 titanium and the watch ships with a flexible strap that's also been inspired by New Balance sneakers. Tag Heuer promises "outdoor-readable screens" and full compatibility with iOS devices. It offers dual-band GPS and a battery that lasts a day and a half per charge. The watchmakers say it can charge from dead to 100 percent in just 90 minutes.

It comes with a Snapdragon 5100+ chip, an AMOLED display and plenty of sensors to track health and fitness. These include a heart rate monitor, a steps counter, a blood oxygen saturation monitor and a sleep tracker, among other sensors.

The only potential downside? The smartwatch runs via a brand-new, untested OS. It comes with a bunch of New Balance training plans preloaded, including options for marathons and 10K races. The companies also promise "gamified prompts" and post-run graphs that "transform data into clarity."

The watch costs over $2,000, which is an extraordinary asking price but not far off from other Tag Heuer products. In addition to the New Balance Edition, the company is offering the smartwatch in a variety of case materials and strap combos, some of which get the price down to $1,600. 

This article originally appeared on Engadget at https://www.engadget.com/wearables/tag-heuer-made-a-smartwatch-with-new-balance-183614594.html?src=rss

Best Amazon Prime Day laptop deals: Discounts on machines from Apple, Lenovo, Dell, HP and more

So you need a new laptop — now’s the time of year to look out for one on sale. October Prime Day, as has been in years past, offers a ton of laptop deals to consider. All kinds of devices are on sale this year for Big Deal Days, from refreshed MacBooks to high-end gaming machines to already affordable notebooks. But sussing out a good deal from a just-ok deal (or even worse, a bad deal all together), can be a challenge. Laptop prices on Amazon are all over the place even when it’s not Prime Day depending on the configuration of the notebook, the brand, the seller and a bunch of other factors.

This is where Engadget can help. We’ve poured over the Prime Day laptop deals available this year to pick out the best ones you can get across all kinds of computers. As always, if you’re super particular about the display panel you want in your next laptop, or you know you want to get as much RAM as possible, we recommend going straight to manufacturers to customize your next PC. But if you’re willing to work with premade models, October Prime Day deals could help you save some cash on your next laptop.

Apple’s latest laptops are the MacBook Air M4 and the MacBook Pro M4, and we recommend getting those if you want a device that’s as future-proof as possible at the moment. You’ll find decent MacBook deals on Amazon throughout the year, and most of them will be on the base configurations. In a welcomed update earlier this year, Apple recently made all base models of the MacBook Air M4 have 16GB of RAM by default (which is the same as you’ll find on the base-level Pros).

You’ve got a lot of variety to choose from when it comes to Windows laptops, and that can be a blessing or a curse. We recommend looking for a laptop from a reputable brand (i.e. Microsoft, Dell, Acer, Lenovo and others like them), and one that can handle daily work or play pressures. That means at least 16GB of RAM and 245GB of SSD storage, plus the latest Intel or AMD CPUs. If you’re looking for a new gaming laptop, you’ll need a bit more power and a dedicated graphics card to boot.

Most Chromebooks are already pretty cheap, but that just means you can get them for even less during an event like Prime Day. However, there are a ton of premium Chromebooks available today that didn’t exist even three years ago, so now is a great time to look out for discounts on those models. In general, we recommend looking for at least 4 to 8GB of RAM and at least 128GB of SDD storage in a Chromebook that you plan on using as your daily driver.

This article originally appeared on Engadget at https://www.engadget.com/deals/best-amazon-prime-day-laptop-deals-discounts-on-machines-from-apple-lenovo-dell-hp-and-more-130507738.html?src=rss

The second-gen Kindle Scribe is $100 off in this Prime Day deal

Amazon devices are, as usual, on sale for fall Prime Day. Case in point: the second-gen Kindle Scribe. The E Ink tablet with 16GB of storage is $100 off, down from $400 to $300, which is a record-low price. If you want more storage, the 32GB and 64GB versions are also 25 and 24 percent off, respectively.

The Kindle Scribe is our pick for best e-reader E Ink tablet. It scored an 86 in our review, thanks to the smooth reading and writing experience it provides. We were also fans of its sleek and slender design. It has a 10.2-inch screen and offers front lights that auto-adjust to your needs. Our biggest gripe was the cost which, thanks to this deal, is less of an issue.

The Kindle Scribe is our pick for best e-reader E Ink tablet. It scored an 86 in our review, thanks to the smooth reading and writing experience it provides. We were also fans of its sleek and slender design. It has a 10.2-inch screen and offers front lights that auto-adjust to your needs. Our biggest gripe was the cost which, thanks to this deal, is less of an issue.

It's worth noting that Amazon announced a few new Kindle Scribe models recently, but none of them are available just yet. The Kindle Scribe 3 has a thinner and lighter design, plus faster page-turning and writing experiences. The Kindle Scribe Colorsoft is Amazon's first full-color E Ink tablet. If you want the latest and greatest, it's worth it to wait — but Amazon hasn't yet named specific release dates for either new model. During its latest hardware event, it only said the new Scribes were coming "later this year."

This article originally appeared on Engadget at https://www.engadget.com/deals/the-second-gen-kindle-scribe-is-100-off-in-this-prime-day-deal-134701405.html?src=rss

Elon Musk and former Twitter execs agree to settle $128 million lawsuit

Over a year after former Twitter executives sued Elon Musk for around $128 million in unpaid severance benefits, both parties have agreed to settle for an undisclosed amount. The settlement is dependent on "certain conditions" being met in the near term, according to a new filing in the Northern District Court of California, but will postpone existing deadlines in the case so Musk can fulfill his obligations.

Former Twitter CEO Parag Agrawal, CFO Ned Segal, chief legal officer Vijaya Gadde and general counsel Sean Edgett originally sued Musk for millions of dollars of unpaid severance benefits in 2024. The justification for their lawsuit was made clear in Walter Isaacson's account of the Twitter acquisition: Musk closed the $44 billion deal early and fired the executives in an attempt to avoid paying out their severance and vested stock options. The executives naturally sued, and now appear to be receiving some amount of what they're owed.

The whole lawsuit likely wouldn't have happened if Musk hadn't originally tried to back out of his acquisition of Twitter, which the company later forced to happen through an extended legal battle. The early days of Musk's ownership of the social network were characterized by drastic cost saving measures as a result, including mass layoffs and the decision to just not pay rent for some of the company's offices.

Finally settling this lawsuit closes the book on that original Twitter saga, with a dismissal of the lawsuit the only real missing milestone. If for whatever reason Musk and X are not able to meet the terms of the settlement, the case will continue on October 31.

This article originally appeared on Engadget at https://www.engadget.com/social-media/elon-musk-and-former-twitter-execs-agree-to-settle-128-million-lawsuit-181915972.html?src=rss

Prime Day Lego deals: Star Wars and Super Mario sets now up to 30 percent off for Day 2

With October Prime Day comes deals on all sorts of things, including tech and toys. Amazon has used the event to kickstart the holiday shopping season for the past few years, making it a good time to pick up early gifts for less and stock up on things for yourself without spending full price. Maybe you haven’t even thought about the holidays yet, but it’s worth giving the latest Prime Day Lego deals a look. A number of Lego sets from the Super Mario and Star Wars collections are already on sale for up to 38 percent off.

When shopping for Lego sets on Amazon, we highly recommend checking a price tracker like Keepa or CamelCamelCamel before buying. It's not difficult to find Lego sets "on sale" at Amazon, but often those discounted prices have been around for a long time. We've clocked "deals" in which the sale price has been available for months already, going back as far as late spring and early summer 2025. Here, we're mostly highlighting discounts on new Lego sets, recent price drops and record-low (and close to them) prices on popular Lego sets from franchises like Star Wars, Super Mario and others.

This article originally appeared on Engadget at https://www.engadget.com/deals/prime-day-lego-deals-star-wars-and-super-mario-sets-now-up-to-30-percent-off-for-day-2-121513856.html?src=rss

Xbox's remaining Game Pass additions for October include Baldur's Gate 1 and 2 and The Casting of Frank Stone

After cramming dozens more games into the service and announcing a 50 percent price increase for the Ultimate tier, Microsoft has revealed the rest of the Game Pass additions for October. They include some games that were previously confirmed to join Game Pass Ultimate and PC Game Pass on their release day, including Ball x Pit (October 15), Keeper (October 17) and Ninja Gaiden 4 (October 21).

Starting today, Game Pass subscribers on the Ultimate, Premium and PC plans can try out a store management game called Supermarket Simulator. Baldur’s Gate 3 fans who have been meaning to check out the first two main entries in the series can hop into the enhanced editions on PC via the Ultimate, Premium and PC variants of Game Pass starting on October 9.

On October 14, folks on those three Game Pass plans can get a pre-Halloween horror fix with The Casting of Frank Stone. This is a Dead by Daylight spinoff from Supermassive Games that taps into the kind of narrative-heavy gameplay the studio used in the likes of Until Dawn and The Quarry.

The other remaining Game Pass additions for October are:

  • The Grinch: Christmas Adventures – October 15 (Game Pass Ultimate, Game Pass Premium and PC Game Pass)

  • Eternal Strands — October 15 (Game Pass Premium, already on Ultimate and PC Game Pass)

  • He Is Coming (Game Preview on PC only) — October 15 (Game Pass Premium, already on Ultimate and PC Game Pass)

  • Ninja Gaiden 2 Black – October 15 (Game Pass Premium, already on Ultimate and PC Game Pass)

  • Pax Dei (PC) – October 16 (Game Pass Ultimate, Game Pass Premium and PC Game Pass)

  • Evil West – October 21 (Game Pass Ultimate, Game Pass Premium and PC Game Pass)

I played some of Eternal Strands earlier this year and dug it quite a bit. It’s an action-adventure game that lets you do some really neat things with elemental abilities. I enjoyed what I played of The Casting of Frank Stone too. That said, Ball x Pit (I got hooked on the demo this summer) and Keeper are the picks of this bunch for me.

This article originally appeared on Engadget at https://www.engadget.com/gaming/xbox/xboxs-remaining-game-pass-additions-for-october-include-baldurs-gate-1-and-2-and-the-casting-of-frank-stone-172448097.html?src=rss

The Bose QuietComfort Ultra headphones are $100 off for Prime Day

The battle for overall wireless headphone supremacy is fiercely contested every year, but when it comes to banishing undesirable noise, Bose usually comes out on top. That was certainly the case when we pitted 2025’s contenders for your cash against each other, and Bose’s QuietComfort Ultra took away the title of best noise-canceling headphones. And right now, the very same headphones are $100 off for Prime Day at $329.

Note that this deal applies to the previous generation QuietComfort Ultra, rather than the refreshed second-gen model Bose has just announced. These offer improved battery life, ANC and audio performance, and they also support lossless audio over a wired USB-C connection for the first time. However, these headphones also cost $449 out of the gate, which is considerably more than the heavily slashed price of their predecessor.

If you don’t have to have the latest and greatest in every product line, the first-gen QuietComfort Ultra will be more than enough for the vast majority of people. They still offer exceptional noise-canceling, very good sound and a comfortable design. Bose’s “Immersive Audio” spatial sound feature can be a bit hit and miss, but with the right content it can be incredible. And while $329 is still a lot of money, $100 is a big saving on what were very recently the best Bose headphones you can buy.

Click here for our rolling coverage of the best Prime Day 2025 deals, which we’ll be updating as the event rolls on.

This article originally appeared on Engadget at https://www.engadget.com/deals/the-bose-quietcomfort-ultra-headphones-are-100-off-for-prime-day-123043790.html?src=rss

Pixel Watch 4 review: A well-rounded smartwatch with a surprising advantage

Everyone uses smartwatches differently. There are the people who wear them all day, those who only wear them when they’re outside, those who only use them while working out and even those who only wear them to bed. In 2025, most smartwatches can do it all and satisfy your needs regardless of how you use them. They perform a lot of basic activity and sleep tracking while serving as excellent passive data gatherers. Google’s latest, the Pixel Watch 4, stands strong against rivals like the Apple Watch Series 11 and Samsung’s Galaxy Watch 8, and if you look just at those model numbers, it’s impressive how far Google has come in just four generations.

The Galaxy Watch 8 is probably the Pixel Watch 4’s closest competitor, considering they’re both compatible with Android while the Apple Watch only works with iPhones. Comparing them can feel a bit futile, since it’s most likely you’ll buy the watch that works best with your brand of phone (i.e. Pixel watch for a Pixel phone, Samsung for Samsung). But it’s still worthwhile to see how they fare against each other. If you know what a Samsung watch can do, it helps contextualize what should be considered acceptable on, say, your Pixel or Apple watch.

It bodes well that for the Pixel Watch 4, I’m no longer questioning its fundamental functionality or complaining about its battery life. Rather, I found myself pondering its adaptability and consistency, as well as its strengths over the competition. Unsurprisingly, thanks to its Google and Fitbit heritage, those strengths lie in AI and health tracking. But the Pixel Watch 4 has a surprising advantage that I never saw coming: charging speed.

Before I get into that though, let’s quickly go over what’s changed on the Pixel Watch 4. It now has a curved display under its domed glass covering, which makes it look even livelier than before. It’s surrounded by bezels that Google says are 16 percent smaller than the last model’s, allowing its screen to be about 10 percent roomier. The display is also brighter by about 50 percent, now going up to 3,000 nits. That’s the same as Samsung’s Galaxy Watch 8, but higher than the Apple Watch Series 11’s 2,000 nits of peak brightness.

Altogether, the physical changes make Pixel Watch 4 look eye-catching and attractive, and I kept getting compliments from people outside my usual tech-savvy circles. Other hardware upgrades include the new dual-frequency GPS, custom haptics engine and speaker, as well as updated processors and a revamped, faster charging system that places the contact points on the watch’s edge instead of the back. Importantly, though I didn’t test it for this review, the Pixel Watch 4 is more repairable, since you can unscrew its case to replace its display and battery if needed.

Like many non-Apple smartwatches, the Pixel Watch 4 runs Google’s Wear OS, but with some new features like a wrist-raise gesture to trigger the Gemini assistant. The company also improved its algorithms for activity- and sleep-tracking, brought its Material 3 Expressive design languages and new watch faces to the OS and overhauled the Fitbit app to center around an AI coach. However, the redesigned Fitbit app wasn’t available for testing during this review, so you won’t see any evaluations of it here.

One more thing I didn’t try on the Pixel Watch 4: Emergency SOS via Satellite. Google’s smartwatch was the first mainstream wearable to be announced to have satellite communications built in, though Apple released the Watch Ultra 3 with similar capabilities shortly after. Because the setup would result in a call or message being sent to emergency services, I decided against testing the satellite feature for this review.

If you’re new to smartwatches or considering your first one, check out our smartwatch buying guide for details on what to expect of a device in 2025. By and large, though, this review won’t cover the basics of what a smartwatch does and what apps or features are typically available.

The Pixel Watch 4 laying on its charger, showing the time is 4:15PM and it's 54 percent charged. The screen also says there is 30 minutes left to fully charge the watch and a ring around its display shows charging progress.
Sam Rutherford for Engadget

I never thought I’d be such a fan of short charge times, but Google’s latest wearable is so fast at refueling that I’ve actually changed my behavior around it. I typically place my smartwatch (usually just the most recent Apple Watch I’ve tested) on my kitchen island so that I see it when I grab my pre-bedtime cup of water and remember to put it on the charger overnight.

With the Pixel Watch 4, I’ve started to just drop it on the charger when I wake up, and by the time I’m done brushing my teeth, washing my face and changing into my gym clothes, it’ll have plenty of power for about half a day. I can’t say the same for the Apple Watch, though the Series 11 has respectable charging speeds that allow me to get enough for a morning walk and a workout after about 10 minutes of being plugged in.

For the actual numbers, you can read my colleague Sam Rutherford’s story where he meticulously charted the charge time of the larger 45mm model of the Pixel Watch 4 he’s been using. It jives with my experience, where, after just six minutes, my device went from 37 percent to 62 percent.

I was also impressed when I saw an alert on the watch’s face that told me the charger wasn’t actually plugged into an outlet. I’ve been burned in the past when I placed other smartwatches on their charging pucks, only to come back an hour later and realize it hadn’t actually been charging because I didn’t connect the cable to a socket. This feature felt like a particularly thoughtful touch on Google’s part.

With such quick recharging, it can feel like a long-lasting battery isn’t as important. But the Pixel Watch 4 still manages to deliver respectable runtimes.

In general, I preferred to let the Pixel Watch 4 get a full charge, because I noticed its battery doesn’t get me through a whole day after just a few minutes on the dock. But when I took it off the charger at 3:35PM one Friday afternoon, it managed to last all through Saturday night, going from 100 percent to 22 percent by 9PM the next day. That’s after a full day of passive activity tracking, where the watch noted that I had burned about 3,000 calories, hiked 6.73 miles and climbed the equivalent of 128 floors.

The Pixel Watch 4 typically lasts about as long as the Apple Watch Series 11. Both devices clock about a day and a half, depending on how frequently I use features like Gemini or the remote control view for the phone’s camera. That runtime also seems similar to the Samsung Galaxy Watch 8, which my colleague Amy Skorheim reviewed.

Considering Google rates the 41mm version of the Watch 4 to last about 30 hours on a charge, the experience I had mostly surpasses that estimate. Of course, battery performance usually deteriorates over time, so my brand new review unit will likely get a little less long-lasting after a while.

Two screenshots of the Fitbit app. The one on the left shows the main dashboard of a person's overall stats on Saturday, October 6. The one on the right shows the sleep page on the same day, with a score of 81 assigned and a total of 6 hours and 24 minutes logged. Below that is a chart with the sleep stages on a timeline.
Fitbit / Engadget

I wouldn’t usually dwell on a feature that has been around for generations of a device, but Google did update its sleep-tracking algorithms for the Pixel Watch 4, calling it “our most accurate sleep-tracking.” Plus, as Apple only just introduced Sleep Score on the Series 11, I thought it was a good opportunity to compare the two.

Both companies thoughtfully limit the brightness of their watches’ displays when you’re in bed, and tuned their software in response to your usual bedtimes so you won’t be awoken by endless notifications while sleeping. They all deliver sleep scores and readouts of the zones you cycled through while you rested, too, to help you get better insight on your slumber.

While I prefer Apple’s presentation of the sleep score in a ring with three segments to indicate areas of potential improvement, I find Google’s charts more readable and specific data easier to find. I’m not going to spend too much time complaining about an app’s layout, though, since it largely has to do with getting used to the way a company organizes its info. What’s more important is how their devices count your sleep, and whether they do so accurately.

In anticipation of a long day that would start at about 4:45AM, I went to bed at about 10PM, only to wake up at 1:57AM, unable to fall back asleep. I counted sheep, told myself to fall asleep, got angry at myself for not being able to sleep and peeked at my phone, which showed me that it had been an hour since I woke up. I finally drifted off after some time, waking up when the Pixel Watch 4 dragged me out of a dream by buzzing relentlessly on my wrist. In my half-awake state, I actually thought the vibration was part of the dream and almost went back to sleep, until I remembered it was the silent alarm I had set for 4:45AM.

Color me shocked when I saw my sleep score was 81 — deemed “Good” by the Pixel Watch 4 due in part to my accumulating six hours and 24 minutes of rest. I immediately dug into the sleep chart to see if my hour awake had been misattributed to sleep. It had been. The device did pick up many moments of restlessness, saying that movement was detected during 9 percent of my sleep. But it couldn’t tell that despite my lying fairly still, I had been, sadly, wide awake.

I can’t penalize Google or Fitbit too heavily for that. Most sleep trackers can’t tell between periods of sleep and complete stillness either. Google said lying awake but very still in bed before you sleep can sometimes be tracked as sleep, and that it’s a known limitation of the algorithm that it’s working on improving for future iterations.

Another area for improvement: napping. On the way home to New York from Lake Placid, I passed out for about an hour at 9PM. Since that was late enough to count as bedtime for some people, I hoped that the Apple Watch and Pixel Watch would both take those minutes into consideration. But neither did.

With the Pixel Watch 4, I found out later that naps during the day would be counted, they just had to last at least two hours. Two-hour naps? In this economy?? I don’t know who else has the time but a quick hourlong lie-down is big for me.

Meanwhile, the Apple Watch was reported to be able to track naps in a watchOS 11 beta, but I’m still waiting on official word and details about that.

Like I said at the start of this review, sleep-tracking isn’t a major reason I use smartwatches. For those, like Sam, who do, the Pixel Watch 4 will be quite satisfying. Sam noted that the device was mostly accurate in his experience, and detected when he had to get up to feed his baby at night. Plus, it’s light and comfortable enough to wear to bed (when paired with the right strap), and its battery will last all night. Add the fast charging we’ve already raved about and it seems like there’s almost no reason to not have the Pixel Watch 4 on your wrist at all times.

I also like that on the Pixel Watch, I was able to set an alarm to wake me with just vibration and no sound, so I could get up earlier than my partner before we left for our five-hour drive to Lake Placid. I could not find this on the Apple Watch — though I did have the option to allow the alarm to break through silent mode. It’s just another way the two companies differ, and I imagine they’ll both copy each other and add the respective missing features soon enough.

A composite of the app drawers on the Pixel Watch 4 and Apple Watch Series 11, showing their app icons.
Google / Apple / Engadget

One thing I do wish Apple would change: the icons for the Stopwatch, Timer and Alarm apps on watchOS. All three of them are represented by orange circles in the app drawer, with slightly different versions of circles with clock hands in them. They’re not labeled, either, so if you’re not in the List view you’ll have to guess which of these three orange orbs is the time-related app you want, and go back and forth until you find the right one.

Google is only slightly better at this, since it uses an hourglass to represent the Timer and the Alarm and Stopwatch icons are a bit more distinct from each other. Plus, Alarm sits at the top of the Pixel Watch’s drawer, whereas the Stopwatch and Timer are closer together near the bottom. They’re clearly organized alphabetically, since other options near the top are Contacts, Calendar and Camera while Recorder, Settings and Spotify are at the end with Stopwatch and Timer.

Meanwhile, all of Apple’s first-party apps are at the top of the watchOS app drawer and if you throw in the other orange circle that is the World Clock, you’ll have four cheesy orbs sitting in close proximity to each other like Ritz crackers.

Samsung’s Galaxy Watch 8 was the first smartwatch to have Google’s Gemini onboard, but when the Pixel Watch 4 launched, it brought the “raise to talk to Gemini” feature with it. This allows for convenient hands-free communication with the AI, so long as you have an internet connection, anyway.

When I left my Pixel 10 Pro in a locker and went for a quick riverside walk, I wasn’t able to get the assistant to set a timer so I knew when to start heading back. This isn’t just about the wrist-raising gesture — Gemini simply won’t work on the Pixel Watch 4 if it’s not online, whether that be via a tethered phone or its own cellular connection. In contrast, while I did have to long-press the Apple Watch’s knob or say “Hey Siri,” I was at least able to get it to set that alarm, even when I put it (and the iPhone it was linked to) on Airplane mode.

This isn’t a dealbreaker, but it’s frustrating if you don’t have an LTE version of the watch and decide to leave your phone at home. Sure, you can touch the screen and use the app to set that timer, but I don’t want to have to stop, lift up my wrist and select the number of minutes my countdown should run.

The Pixel Watch 4 on a wrist held up in mid-air, with its screen saying
Cherlynn Low for Engadget

There are a few caveats to note when specifically talking about the wrist-raise gestures, too. For one, you’ll have to make sure the Always On Display is enabled, since the system relies on the screen being on to detect changes in movement and state. You’ll also have to be fairly deliberate with the gesture, bringing your wrist to your mouth from about waist-level.

For the most part the Pixel Watch 4 responded as expected, with the onscreen indicator telling me Gemini was listening when I brought my hand to my mouth. But every now and then, especially when I was sitting down, it would fail to react. There are few situations more embarrassing than sitting in a cafe, repeatedly jerking your wrist up to your face while holding a phone up to get a video of the feature working. I could only hope the other people at the coffee shop where I was writing this review didn’t think I was doing something worse.

Sometimes, the little glowing animation would appear to show that my action was successful, but if I even moved my wrist slightly after that, it would disappear. Also, if you lift your wrist from any screen other than the home page, you won’t see the indicator. But if you confidently speak your request into the ether anyway, you’ll realize Gemini was actually awoken by your gesture.

With the apps drawer open, I lifted my wrist and asked what the weather was like, and promptly got a response. There was also a light vibration to let me know the watch had heard me. When I raised my hand again and asked “how about tomorrow,” Gemini was quick to tell me it would be rainy in my area. I was impressed by the speedy responses and the fact that I could keep bringing my hand up to my mouth to ask follow-up questions or interrupt an overly wordy response, but I do have to acknowledge that there is a certain finesse that is required to get the gesture right each time.

I was a little perturbed that the action needs to be somewhat deliberate, right up until the one time it accidentally triggered when I flipped my wrist during a call. Out of nowhere, the assistant was responding to my conversation with my therapist. This only happened once during my 10 or so days with the Pixel Watch 4, so the rate of false positives is fairly low. The jerkiness of raise-to-talk to Gemini is a tradeoff I’m willing to make in exchange for fewer accidental triggers.

Plus, Google has said this is an initial foray into gesture-based interaction with the Pixel Watch, and it appears to continue to tweak its algorithms for greater accuracy and sensitivity. The Watch 4 may not currently support the double tap and wrist flick gestures that Apple does (or Samsung’s pinch-based actions). But I’ve been in the industry long enough to remember when Android Wear watches allowed you to flip your wrist to scroll through long notifications. It seems Wear OS still supports that, along with a limited set of gesture-based navigation actions. I was able to dismiss notifications and return to the home page by rotating my wrist on the Pixel Watch 4 thanks to the existing “ungaze” gesture that’s designed to close an alerting notification.

The Pixel Watch 4 on a wrist held up in mid-air, with the Gemini logo on its screen.
Cherlynn Low for Engadget

Over the years, Google has gone back and forth on its auto-workout-detection system. With the original Pixel Watch, the device didn’t bother to tell you if it noticed you had gone on a walk. You’d have to go into the Fitbit app a few hours later to see that session. That changed with the Pixel Watch 2, which brought reminders to start a workout for seven types of activities including running, walking, rowing and outdoor biking. The Watch 3 improved upon that by being quick on the uptake, suggesting I had been active as soon as I had been moving for 10 minutes.

On the Watch 4, Google changed its approach (again). At first, it no longer appeared to automatically track my daily 20-minute walks to and from my gym. But because I remembered my experience with the original model, I went to the Fitbit app on my phone and was relieved to see a suggested workout logged there.

Subsequently, I discovered that the Watch 4 would prompt me to confirm detected periods of activity, but only 30 minutes after I was done. The idea is that the prompt to record a walk or impromptu run might interrupt your flow, and while I can understand that rationale, I wish there was an option for me to just set it how I prefer it.

The good news is that in my time with the Pixel Watch 4, I never felt shortchanged. As long as they lasted at least 15 minutes, pretty much all my extended walks were accurately logged (minus the location information, which makes sense from a privacy perspective). I also wore a Galaxy Ring during my review, since in my experience that’s the most accurate at tracking every little walk I take, and the two devices usually matched up. The Apple Watch, meanwhile, barely ever registered any of my walks, and I always needed to remember to manually start an Outdoor Walk workout.

With its new dual-frequency GPS, the Pixel Watch 4 is better at mapping out my routes than its predecessors, especially in building-dense cities like the one I live in. I never noticed a significant delay in the watch latching onto a signal, even as I walked out of a small tunnel into the skyscraper-rich Newport area of New Jersey.

Two screenshots showing the Fitbit app's exercise section for the period of September 28 to October 4. The first one is the top part of this page, saying the user had met five out of their five target exercise days. The rest of this and the second screenshot show logged activities, including walks, HIIT, strength and circuit training.
Fitbit / Engadget

Each of this year’s new smartwatches has some unique features. Samsung has its antioxidant index test, Apple has hypertension notifications and Google has had loss of pulse detection and body response alerts. That latter basically notices changes in your electrodermal activity and prompts you to note if you’re feeling particularly stressed or excited. It’s been around since the Pixel Watch 2, and isn’t enabled on the fourth-generation device by default so you won’t have to worry about it pinging you too much. I had it activated and was buzzed several times most days to think about my mood, and each evening I’d have a nice log of how many times I was agitated.

There are quite a few new features on the Pixel Watch 4 that I won’t spend too much time evaluating. The real-time streaming of your bike workout stats to your connected phone is one example. Like Apple’s version of this feature, it works and makes it easy to see your stats safely on a mounted handset during your ride.

Google also introduced something called “notification cooldown” which minimizes interruptions after several of them come through in rapid succession. If your group chat is getting particularly fiery, for example, this can help reduce the amount of vibrations and alerts being sent to your wrist after some time. I made my friend Julian Chokkattu at Wired test this out with me and we sent each other single-word messages nonstop for minutes at a time and both of us found notification cooldown kicked in after a few alerts.

Speaking of, the Pixel Watch 4 also features AI-generated suggested replies to messages that support the Wear OS quick reply protocol. Google said this is a first-of-its-kind small language model designed for use on a watch. Because it’s on-device, it won’t require an internet connection to work, though if you’re receiving messages I have to imagine you’re at least connected to cellular. When it did work, it was nice to see the smart reply suggestions instead of the generic canned ones before. But most of the apps I use, like Telegram and Instagram messages, don’t support quick reply. Google also says smart replies won’t work on Workspace or select WhatsApp messaging.

The interface you’re most likely to interact with on any smartwatch is your main watch face, and in general the new watch faces on the Pixel Watch 4 are rich with information and shortcuts. While I wish Google would move away from the cartoonish, rounded fonts in favor of something cleaner and sharper, I like that all its layouts offer plenty of customization options with lots of room for convenient complications. I chose to put my most important stats on my home screen, as well as a shortcut to launch Spotify. I do wish Google would make nicer faces like Apple’s Photos one that has a dynamic clock to better highlight your pictures, instead of the current option on the Pixel Watch that sticks the text in the bottom and calls it a day.

The Pixel Watch 4 on a wrist, with its screen showing a trophy graphic and the words
Cherlynn Low for Engadget

When I reviewed the Pixel Watch 3, it felt like the first time Google’s smartwatch was on par with the likes of Apple’s and Samsung’s offerings. With the Pixel Watch 4, not only is Google closing the gap even further than it did last year, but it’s also bringing unique tools you won’t find elsewhere. This year’s model differentiates itself with a repairable design, super fast charging and, though it’s no longer the only one on the market to offer this, satellite communications. The first two alone feel like game changers, and even with its limitations, raising your wrist to talk to Gemini is a convenient gesture when it works.

Beyond the new features sit the comprehensive suite of health-related tools that make the Pixel Watch 4 a formidable smartwatch and excellent companion for your smartphone. Wear OS and Material 3 Expressive make for a vibrant, easy-to-navigate interface for a system that can do almost anything your phone can, just on a smaller screen.

At $350, the Pixel Watch 4 is $20 more than the Galaxy Watch 8 (and $50 less than the Apple Watch Series 11). It’s hard to justify that exact price difference and tell you which is a worthier purchase. My recommendation remains the same as ever: Get the watch that’s from the same company as your phone. It’ll be better for you.

This article originally appeared on Engadget at https://www.engadget.com/wearables/pixel-watch-4-review-a-well-rounded-smartwatch-with-a-surprising-advantage-170059851.html?src=rss

The best thing about the Pixel Watch 4 is Google’s new charger

The Pixel Watch 4 is arguably the best looking smartwatch on the market. When you consider that the biggest design changes on the new model are a curvier glass dome, a larger display and slimmer bezels, you could've said the same thing about its predecessor. And while the Pixel Watch 4 also features improved health and fitness tracking and a more lively UI, the best thing about Google’s latest wearable isn’t even the watch itself. On the Pixel Watch 4, the charger is by far the biggest upgrade.

The original Pixel Watch came with a wireless charging puck, which was super convenient and easy to use. I also appreciated that even though it didn't officially support the Qi wireless standard, you could reverse charge it with your phone just as long as you positioned it just right. That meant for short trips like a weekend getaway, you could simply leave the charger at home and travel super light while relying on your phone to pull double duty. The issue was that even in ideal conditions, the watch charged slowly, and when combined with lackluster battery life, you often ended up with a device that ran out of juice at inopportune times.

Not only did pins on the Pixel Watch 3's charger make it finicky to use, if you didn't align the watch just right, sometime it wouldn't even charge at all.
This is the little devil that made charging the Pixel Watch 2 and 3 more annoying than it should have been.
Sam Rutherford for Engadget

For the Pixel Watch 2, Google sought to address this by switching to a charging cradle with pins that offered a higher power output. This is where my frustrations began. Because the pins on the charger needed to be aligned precisely, you could only mount the watch one way (i.e., the crown had to point the same direction as the charger’s wire). This might not sound like a big deal, but it made keeping the watch topped off harder than it should have been and often felt just as finicky as the "unsupported" phone-based reverse wireless charging available on its predecessor.

The really annoying part is that the connection between the watch and the charger was so particular that I lost count of the number of times I thought I connected the watch to the puck before going about my normal morning routine, only to come back 45 minutes later to a still dead wristpiece. So not only did Google trade convenience for marginally faster charging (which still wasn't speedy enough imo), the company made the whole process more unreliable. And much to my dismay, the Pixel Watch 3 used the same charger as the Watch 2.

Not only is the Pixel Watch 4's charging cradle much easier to use, it's design means there's no confusion about how to properly position the watch.
Not only is the Pixel Watch 4's charging cradle much easier to use, it's design means there's no confusion about how to properly position the watch. 
Sam Rutherford for Engadget

But on the Pixel Watch 4, Google provides a new cradle that makes almost everything so much better. Instead of charging pins, there are just two little contacts that touch the side of the watch. The added benefit of this is that now the screen is positioned vertically instead of lying flat on the table, which allows the watch’s display to also double as a little clock while it's recharging. Cute and useful! Also, due to the charger’s design, there’s no confusion about which way you need to place the watch — there’s a dial in the way on the “wrong” side. No amount of fiddling will make the watch sit right if you place it incorrectly. I just wish the charger had a USB-C port instead of a captured cable, so if anything happens to the cord, you could simply swap in another instead of potentially having to replace the entire thing.

Of course, the biggest benefit is significantly improved charging speeds. To best illustrate the difference, I took the Pixel Watch 3 and Pixel Watch 4, connected them to their respective chargers and recorded their battery percentage every 10 minutes for an hour. And just to make things as fair as possible, I used Google's new 67-watt dual-port fast charger as the power adapter for both.

After just a 30 minute charge, the 45mm Pixel Watch 4 hit 94 percent battery while a 45mm Pixel Watch 3 was still at 58 percent.
Compared to the Pixel Watch 3, the Pixel Watch 4 charges nearly twice as fast and all you really need is 30 minutes to get two full days of use compared to over an hour for its predecessor. 
Sam Rutherford for Engadget

After just 30 minutes, the Pixel Watch 4 was basically done as it hit 94 percent. At that point, the Pixel Watch 3 was way behind at 58 percent. In fact, I had to give the Pixel Watch 3 an extension, because even after an hour, it only had an 85 percent charge. It took an extra 20 minutes after that just to crack 90 percent. So not only does the Pixel Watch 4 power up faster, it has a much better charging curve that effectively cuts your daily recharging time in half.

Google has finally turned the Pixel Watch's battery life into a non-issue, thanks to faster charging and improved longevity. I get two and a half days easily, even with its always-on display enabled. Though in a perfect world, I would love it if smartwatches only had to be charged once a week. Regardless, the process of keeping the Pixel Watch 4 running isn't a chore like it was for previous models. I can simply drop it on the cradle while I wrangle the kids and grab some caffeine after waking up, and I know that it'll be ready to go as soon as I am.

Thanks to tweaks like a larger, curved glass screen with smaller bezels, the Pixel Watch 4 is arguably the best looking smartwatch on sale today.
Thanks to tweaks like a larger, curved glass screen with smaller bezels, I'd argue that the Pixel Watch 4 is the best looking smartwatch on sale today.
Sam Rutherford for Engadget

Admittedly, this isn't a groundbreaking development, and in some ways, I feel like Google should have figured this out a generation or two ago. But sometimes small upgrades can have a big impact, especially on a device that looks this good and now functions even better than before.

This article originally appeared on Engadget at https://www.engadget.com/wearables/the-best-thing-about-the-pixel-watch-4-is-googles-new-charger-170052942.html?src=rss

Google Pixel Buds 2a review: Affordable earbuds that are better with ANC

The Pixel Buds Pro 2 have been the best earbuds for Pixel phone owners since they arrived last fall. With the Pixel Buds 2a ($129) though, there’s no longer a clear-cut buying decision. This more affordable model finally has active noise cancellation (ANC) as just one of its many updates. It makes sense, then, that the Pixel Buds 2a are more expensive than their predecessors, the Pixel Buds A-Series. Still, there are sacrifices to be made if you decide to save $60 by choosing them over the Pro 2.

The biggest upgrade on the Pixel Buds 2a is the addition of active noise cancellation. On the previous A-Series earbuds, Google opted to retain any ANC abilities for the pricier Pixel Buds Pro line. While the company continues to reserve its best ANC performance for that model, the Pixel Buds 2a will still deliver some level of relief. It’s nowhere near what the best noise canceling earbuds can muster, but in most circumstances, it’s better than nothing.

Another major change is the updated design. Google decided to keep its earbud aesthetic consistent, so the 2a mirrors the Pixel Buds Pro 2 with a tiny stature and the “twist-to-adjust stabilizer” instead of a “stabilizer arc.” The new version of the stabilizer is more of a hump than anything else, but it’s just enough to hold the earbuds in place. Overall, the combination of size and the stabilizer offer a comfortable fit, with balanced weight that never feels like you’re hauling something on the sides of your head.

In addition to the improved comfort, Google bolstered the sound quality on the Pixel Buds 2a as well. You still get spatial audio, albeit without head tracking, but these earbuds do well with non-immersive content too. Through a range of genres from metal to jazz, the 2a offered crisp, detailed sound while much of the competition in this price range struggles with clarity. Oftentimes a set of $130 earbuds will come off muffled, like in Turnstile’s “I CARE,” but the Pixel Buds 2a keep the kick drum punchy and the vocals clear.

Bass performance is another area where midrange earbuds tend to struggle, but the 2a holds its own with respectable performance here. Throughout Deftones’ private music, it maintained the low-end growl of Stephen Carpenter’s 7- and 8-string guitars. The tuning wasn’t just relegated to handling Abe Cunningham’s bass drum. And it’s not just raucous genres either: there’s plenty of deep tone in Ruston Kelly’s acoustic guitar on Pale, through the Window.

Another perk of the Pixel Buds 2a is their Hearing Wellness updates that help you maintain healthy listening habits. In the Pixel Buds app, you’ll see both current listening and exposure levels, as well as comparisons for the last 24 hours and seven days. You can also opt to receive volume level notifications so you’ll be aware when you exceed the exposure limit. The hearing health tools on the Pixel Buds Pro 2 are more comprehensive, but it’s nice to see level tracking on a set of mid-range earbuds. It’s certainly better than nothing.

The Pixel Buds app offers access to settings and the hearing health feature.
Billy Steele for Engadget

Besides more robust ANC performance, there are several differences between the Pixel Buds 2a and the Pixel Buds Pro 2. Those are almost entirely the advanced features the pricier model offers, despite both sets having the same Tensor A1 chip. Of those, there are three major tools the 2a doesn’t have: Adaptive Audio, Loud Noise Protection and Conversation Detection. The first two are new additions to the Pixel Buds Pro 2 in recent weeks, but they provide automatic adjustments that either maintain audio performance or assist with hearing health.

You also won’t be able to use head gestures to answer calls or reply to texts like you can on the Pixel Buds Pro 2. And for Gemini users, the ability to converse with Google’s AI in noisy environments isn’t available on the 2a either. You can still talk to Gemini Live on these cheaper earbuds, but you’ll need to be mindful of ambient noise levels when doing so.

Another key difference between the 2a and Pro 2 is related to battery and charging. The biggest issue here is the Pixel Buds 2a’s case doesn’t support wireless charging. Battery life on the Pro model is eight hours with ANC off or 12 hours with it on. On the 2a, that's seven hours and 10 hours respectively. During my tests with the Pixel Buds 2a, I easily got a full workday out of the earbuds with a mix of ANC and transparency mode. That’s what I’d consider “normal” use with the former setting for focus time and the latter for calls and keeping tabs on my mischievous cocker spaniel.

While the Pixel Buds 2a are equipped with what Google calls “AI-powered Clear Calling,” they don’t have the same beamforming microphones and voice accelerometer as the Pro 2. As a result, voice performance suffers on the more affordable model. It’s perfectly fine for casual conversations and last-minute work chats, but you’ll want something better for situations when you’re recording audio or leading the discussion.

Lastly, the Pixel Buds 2a don’t have onboard volume controls. This is the biggest dealbreaker for me. In the year 2025, it’s infuriating to have to reach for my phone or keyboard to adjust the volume of my music or podcasts (looking at you, AirPods 4). I understand Google had to sacrifice some features to sell the 2a for $129, but this is a basic one I really wish it had kept.

You can certainly use the Pixel Buds 2a with an iPhone or Galaxy device, but like the Pixel Buds Pro, you’re going to get the best out of these if you have a Pixel phone. Like Google’s previous models, these were built to be a conduit to Gemini Live and you’ll sacrifice some of the main features if you use the 2a with a non-Pixel device.

If you do have a Pixel handset, there’s a lot to like here, including punchy sound, a comfy fit and respectable battery life. The limited hearing health tools are still handy and the addition of ANC is a welcome change. The best Google has to offer on Pixel Buds is still exclusive to the Pro 2, but the 2a is a perfectly capable audio companion for most Pixel phone owners.

This article originally appeared on Engadget at https://www.engadget.com/audio/headphones/google-pixel-buds-2a-review-affordable-earbuds-that-are-better-with-anc-170052705.html?src=rss

Google Pixel 10 Pro Fold review: The tankiest foldable

Every good device builds upon the generation that came before it. In the seven years or so that foldable phones have been around, we've seen some incredible breakthroughs. For all its flaws, the original Galaxy Fold was a magical creation that proved there was merit to Samsung’s sci-fi aspirations. Then the Galaxy Z Fold 3 added water resistance to a foldable for the first time plus built-in stylus support. More recently, Google simplified flexible phone design with the Pixel 9 Pro Fold, proving manufacturers didn't need to mess around with funky aspect ratios before Samsung achieved unprecedented levels of thinness with the Galaxy Z Fold 7 earlier this summer.

However, there's one thing that has become a standard feature on standard high-end smartphones that hasn't been available on foldables until now: top-tier dust resistance. That changes now thanks to the IP68 rating on the Pixel 10 Pro Fold. Not only does this solve one of the biggest shortcomings of foldables overall, but it gives you additional protection against one of life's everyday foibles. So while Google's latest flexible phone isn't nearly as slim or sleek as the Z Fold 7, it is the best option for folks who prefer a tankier device.

While the Pixel 10 Pro Fold (P10PF from here on out) might look like a carbon copy of last year's phone, there are a handful of subtle changes throughout. Google shrunk its hinge and made it more durable. It also shaved down parts of its aluminum frame — specifically the border to the left of its outside screen. As for the displays themselves, they're even brighter than before at 3,000 nits (up from 2,700 nits) while the size of P10PF's exterior panel has increased slightly to 6.4 inches (0.1 inches larger) by reclaiming some space that used to be bezel. And I still love the P10PF's 8-inch main screen for watching movies and reading comics, even with the cutout for its interior selfie cam in the top right corner. That said, if the presence of a rounded corner encapsulated by a right angle messes with your OCD tendencies, Google still hasn't found a fix for that.

The biggest shortcoming of the Pixel 10 Pro Fold may be its thickness, because at 10.8mm compared to just 8.9mm for the Galaxy Z Fold 7, it's significantly heavier and bulkier to carry around.
The biggest shortcoming of the Pixel 10 Pro Fold may be its thickness, because at 10.8mm compared to just 8.9mm for the Galaxy Z Fold 7, it's significantly heavier and bulkier to carry around. 
Sam Rutherford for Engadget

As for the P10PF’s IP68 rating, which denotes the phone's ability to withstand intrusion from dust and immersion in water, this upgrade might not sound like a huge deal. But as someone whose daily driver was a Pixel 9 Pro Fold last year, I was sure to toss it in a waterproof bag when I went to the beach. That's because even though I had no intentions of actually swimming with it, I wanted to make sure sand wouldn't find its way inside. The sound of dust, dirt or other particles grinding in a foldable's hinge is deeply unpleasant and should be avoided at all costs. And thanks to the addition of a proper IP rating, you don't need to treat the P10PF like the Bubble Boy every time you want to enjoy a day at the shore.

After Google debuted an all-new design on last year's phone, it's probably a bit much to ask for a full revamp 12 months later. Sadly, this means its size and weight haven't changed much, with the P10PF coming in at 9.1 ounces (258 grams) and 10.8mm thick when closed. If this phone had come out back in the spring, that might not have been an issue. However, with the arrival of the Galaxy Z Fold 7 and its wonderfully thin and light design (7.6 ounces and 8.9mm when closed), it's hard to go back once you've experienced a foldable phone that doesn't have any of that excess heft. While I appreciate the added durability and tankiness we're getting now, here's hoping Google can put all of this in a leaner chassis next fall. Lastly, while the rest of the Pixel 10 family is going full eSIM for this generation, I appreciate that the P10PF still comes with a physical SIM card tray.

For everyday tasks, the Pixel 10 Pro Fold's Tensor G5 chip is vary capable. However, compared to rivals like the Z Fold 7, it lacks the high-end performance you get from something like the Snapdragon 8 Elite.
Don't mess with Teemo or else he will throw a mushroom at you. 
Sam Rutherford for Engadget

Like its pro siblings, the P10PF comes with a Tensor G5 chip, 16GB of RAM and up to 1TB of storage. In everyday use, that's more than enough oomph to make everything feel swift and snappy. Meanwhile, the arrival of Google's Material 3 Expressive UI update makes the whole phone feel even more lively, which makes even simple things like flipping between apps or customizing your homescreen that much more enjoyable.

However, in terms of graphics performance, Google's Tensor G5 still can't quite keep up with flagship silicon from Qualcomm and its Snapdragon 8 Elite processor. That's because the Pixel 10 Pro Fold just isn't the best choice for hardcore gaming despite improved loading speeds. Unfortunately, a number of our regular tests like Geekbench 6 aren't available (as we're reviewing the phone prior to its official release), which makes getting concrete numbers a bit tricky. When running those apps on the Pixel 10 Pro XL (which features the same chip and memory), the Tensor G5 produced a multi-core score of 6,091 on Geekbench's Compute test. That’s more than 30 percent lower than what we got from the Galaxy Z Fold 7 (9,271).

There's a new multitasking feature in the Pixel 10 Pro Fold that lets you customize the size of apps in split-screen mode and quickly expand them simply by tapping on their respective window.
Sam Rutherford for Engadget

I wouldn't necessarily mark this down as a dealbreaker, as the P10PF's less prodigious performance isn't something you'll notice all the time. But if you do a lot of mobile video editing or hardcore gaming, that does make Google's latest foldable harder to recommend compared to the Z Fold 7.

On the bright side, Google has added some enhanced multitasking features, most notably a new split-screen UI that lets you choose exactly how big you want two apps to be when opened in split-screen mode. Furthermore, you can leave one app open in a tiny sliver on either side and tap to quickly switch between the two, sort of like the card-based UI OnePlus created for the Open. It's very handy and makes it easy to flip back and forth between things like emails and messages or your calendar, though I really wish Google would give us the ability to permanently pin the P10PF's taskbar to the bottom of the screen like you can on Samsung's handset. 

The new UI for the Pixel 10 Pro Fold's camera app makes much better use of the phone's big flexible screen.
The new UI for the Pixel 10 Pro Fold's camera app makes much better use of the phone's big flexible screen. 
Sam Rutherford for Engadget

Elsewhere, there's a new layout in the camera app that better utilizes the phone's main screen by putting the camera's viewfinder on the right while your photo roll appears on the left. This gives you an instant, big-picture view of every photo as soon as you take it without stopping you from setting up for the next shot. And for people who need extra help getting a good reaction from kids while posing for a shot, Google has also added some fresh animations to its Made You Look feature.

The Pixel 10 Pro Fold has the same rear cameras as its predecessor: a 48MP main cam, a 10.5MP ultra-wide and a 10.8MP telephoto cam with a 5x optical zoom.
The Pixel 10 Pro Fold has the same rear cameras as its predecessor: a 48MP main cam, a 10.5MP ultra-wide and a 10.8MP telephoto cam with a 5x optical zoom. 
Sam Rutherford for Engadget

While the cameras on the P10PF are the same as the ones in its predecessor, it's still the best way to capture sharp, colorful and detailed pics with a foldable phone. During the day, the P10PF consistently captured more accurate hues and tones than the Galaxy Z Fold 7 (which has a tendency to exaggerate rich colors). And in low light, Google's Night Sight mode remains unmatched.

In a tricky shot of a money cat taken in very low light, the P10PF's photo was noticeably brighter and more detailed, while a pic of some spooky skeletons was sharper and featured richer colors. On top of that, the Z Fold 7 tops out with a 3x telephoto zoom, but the Pro Fold sports a 5x optical lens that gives you more reach for long-distance images. 

If that wasn't enough, Google also gave the P10PF the ability to edit images solely using your voice, which is not only a time saver but a fantastic option for anyone who doesn't want to fiddle around with toggles and sliders to enhance their photos. Sadly, the coolest new feature from the Pixel 10 Pro line — Pro Res Zoom — isn't available on the Pro Fold, so you have to settle for a max zoom range of 20x instead of 100x.

Packing a 5,015mAh cell, the Pixel 10 Pro Fold's battery is nearly 10 percent larger than last year's model, which resulted in notable gains on our local video rundown test. When using its exterior display, it lasted just over 27 hours (27:02), almost an hour longer than what we got from the Galaxy Z Fold 7 (26:22). Naturally, the P10PF doesn't last nearly as long when using its larger interior display. However, with a time of 21:20, that still leaves a lot of room for activities.

Even if you don't use it for charging, being able to slap magnetic accessories on the back of the Pixel 10 Pro Fold is super useful. Plus, this is the first phone to feature full support for the Qi2 standard.
Even if you don't use it for charging, being able to slap magnetic accessories on the back of the Pixel 10 Pro Fold is super useful.
Sam Rutherford for Engadget

When it comes to recharging, the Fold has gotten some upgrades there too. Wired speeds have risen slightly to 30 watts (up from 21 watts), while wireless rate has doubled to 15 watts. This comes thanks in large part to Google's newfound support of the Qi2 standard, which also brings compatibility for magnetic accessories. That means now you can use the kind of accessories iPhone owners have enjoyed for years (Google calls this feature PixelSnap on its phones) and alongside its new IP68 rating, this might be one of the biggest upgrades to the phone's general usability.

The addition of proper dust and water resistance on the Pixel 10 Pro Fold has removed one of the last two shortcomings of modern foldables, which is no mean feat. However, at $1,799, the price barrier is still hard to overcome for most folks. On top of that, when compared to its biggest rival, it'd be a mistake for anyone interested in big and expensive flexible phones to ignore the Galaxy Z Fold 7. Its super sleek design simply cannot be denied. Plus, higher performance, more freedom to open additional windowed apps and the option for a permanently pinned taskbar make Samsung's rival the preferred pick for gamers and power users.

I love the addition of a proper IP68 rating, but I hope Google can put that in a thinner chassis next year.
Sam Rutherford for Engadget

When it comes to the category as a whole, the P10PF offers the best photo toolkit around. There’s also Google's excellent (and ever-growing) stable of handy AI-powered features and my preferred skin for Android 16. Factor in longer battery life, improved multitasking and true Qi2 wireless support for the first time on any foldable, and you have a recipe for a versatile and surprisingly rugged flexible phone.

This article originally appeared on Engadget at https://www.engadget.com/mobile/smartphones/google-pixel-10-pro-fold-review-the-tankiest-foldable-170051471.html?src=rss

Google wants to see your feet (for virtual shopping purposes)

Google recently started letting you try on clothes from the comfort of your home by uploading a photo and letting AI take care of the rest — and if you’re in the US, you can now do the same thing with shoes. Fortunately, the process isn’t nearly as creepy as Google needing a close-up of your bare feet. Rather, when you’re browsing shoes, you tap the pair you want to try on and upload a full-length photo of yourself in any old outfit.

Google will then swap out whatever shoes you’re wearing in the original photo for the ones you’re interested in buying, so you can see how they look with a particular outfit. For the best results, it advises that you stick to solo photos in which you’re standing upright, with good lighting and a background that isn’t too busy. Your clothing shouldn’t be too baggy either. And naturally, Google warns to only use photos of yourself or those you have permission to use from someone else. It won’t accept photos of children, either.

Google points out that the image it generates is designed to help you see how an item might look, but doesn’t guarantee that it’ll actually fit you in real life. It’s an approximation, then, rather than an image that perfectly takes into account your body shape and personal features. This is probably more of a catch when you’re for clothes than shoes, though. Just don’t walk into a store and blame Google when the sneakers you tried on virtually aren’t manufactured in your real-world size.

Google says that no biometric data from the photo you upload is collected or stored, nor will it use the image for training purposes. It won’t share it with other Google apps or third parties either, but you can delete both the original photo and any generated images if you’d rather not let it hang onto them.

Google has been gradually improving the capabilities of its AI as a virtual shopping assistant. When you use AI Mode to help you find a particular item now, such as a pair of jeans, you can make more specific queries about their style and ask follow-up questions to the chatbot to narrow down the visual results further.

This article originally appeared on Engadget at https://www.engadget.com/ai/google-wants-to-see-your-feet-for-virtual-shopping-purposes-165446054.html?src=rss

Get $200 off the Samsung Galaxy S25 for Prime Day

It's not as flashy as the Galaxy Z Fold 7, but Samsung Galaxy S25 still gets you a great smartphone experience, just in a more traditional package. If you want to see for yourself, during Prime Day, you can get a Samsung Galaxy S25 for $660, $200 off its normal price and close to the phone's lowest price to date.

The Galaxy S25 is a mix of old and new. The phone largely looks like the Galaxy S24, but comes in new colors and a slightly thinner frame. It uses the same bright 6.2-inch, 120Hz AMOLED screen, but is powered by the Snapdragon 8 Elite chip. You're stuck with the same 50-megapixel wide, 12MP ultra-wide and a 10MP 3x telephoto, but the phone (sort of) supports Qi2, if you're willing to add on a case. The list goes on, but what matters, based on Engadget's review of the smartphone, is that battery life is long and Samsung seems to be delivering on the promise of smartphone AI features.

In terms of battery life, the Galaxy S24 already started out strong at around 24 hours, but the Galaxy S25 goes a good bit past that with an additional four hours. That gives you more time for calls or watching videos — one of the tangible benefits of a power-efficient 3nm Qualcomm chip. That performance also shines when it comes with AI. Samsung offers its own collection of Galaxy AI features, like the less-than-useful Now Brief and AI photo editing, but it's also just a good vehicle for Gemini. Google debuted the ability for Gemini to take action across on-device apps and services on the Galaxy S25, and it works well.

At $800, a Galaxy S25 that largely carries over the features and components of the S24 isn't necessarily appealing. But for $200 off for Prime Day, and a guaranteed 256GB of base storage, purchasing Samsung's cheapest Galaxy S25 starts to make a lot more sense.

This article originally appeared on Engadget at https://www.engadget.com/deals/get-200-off-the-samsung-galaxy-s25-for-prime-day-100037363.html?src=rss

Verizon buys Starry to expand its wireless broadband footprint

Verizon is buying the smaller broadband carrier Starry for an undisclosed sum. The acquisition is expected to close by the first quarter of 2026, but is subject to FCC approval. Verizon has already done some work to appease the US government by ending DEI initiatives, so the FCC is likely to give this merger its stamp of approval.

This acquisition should help Verizon expand its wireless broadband footprint throughout the country. Starry specializes in delivering high-speed internet to multi-dwelling units (MDUs) and urban communities. These environments are difficult to adequately cover, as urban settings present some unique challenges.

Starry gets around this by employing its proprietary millimeter wave technology, which Verizon will now own. Simply put, the company installs nodes throughout populated areas that broadcast concentrated radio waves that are picked up by receivers outside of apartment buildings and the like. This allows for a service that rivals a fiber connection when it comes to downloads, but everything is done wirelessly.

The company has experienced rapid growth these past several years, with more than 100,000 customers in cities like Boston, Los Angeles, New York City, Denver and Washington DC. "Starry has demonstrated a unique and efficient approach to delivering high-speed internet in complex MDU environments," said Joe Russo, executive vice president of Verizon. "By integrating their technology and expertise, we will accelerate our fixed wireless access capabilities."

This article originally appeared on Engadget at https://www.engadget.com/big-tech/verizon-buys-starry-to-expand-its-wireless-broadband-footprint-163557816.html?src=rss

DJI's popular wireless Mic Mini kit is discounted to $99 for Prime Day

If you're a creator in the market for a good-quality wireless microphone, DJI has not just one but two of its best products on sale for October Prime Day. The Mic Mini, which is already a good deal at the regular $169 price, is marked down to just $99 for a savings of 41 percent. And DJI's Mic 2, which offers features like 32-bit float recording and support for external microphones, is currently available for $269 or $80 off the regular price

DJI's Mic Mini bundle includes two mic transmitters and a receiver that can be connected to a camera or phone, along with a charging case. The mics weigh just a third of an ounce and attach easily to subjects via magnets or clips. Everything pairs automatically and they offer high quality 24-bit, 20Hz to 20K Hz recording. They also connect easily to smartphones over Bluetooth and other DJI devices like the Action 5 Pro and Osmo Pocket 3 cams using DJI's OsmoAudio direct connection. With a range of 1300 feet and 48 hours of battery life with the charger case, they're an excellent addition to a creator's bag of tricks.

DJI's wireless Mic 2 can not only be connected to a mirrorless camera via a 3.5mm cable, but also supports Bluetooth audio to easily pair with a smartphone as well. It can transmit at a range of up to 820 feet (less with a Bluetooth connection) and automatically reduces background noise like wind, city sounds and even drone noise. Sound quality is exceptional thanks to the 20 to 20K Hz frequency response and up to 32-bit float recording internally. And for professionals (and unlike the new Mic 3), you can connect external microphones from Shure, Sennheiser and others if you want. This deal includes two mic transmitters, a receiver for your camera, a charging case and wind muffs.

This article originally appeared on Engadget at https://www.engadget.com/audio/djis-popular-wireless-mic-mini-kit-is-discounted-to-99-for-prime-day-163220479.html?src=rss

The Beats Studio Pro are on sale for $170 this Prime Day

Amazon Prime Day is upon us and that always means some steep discounts, including on headphones, so if you've been thinking about upgrading your audio, now's a good time to buy. Beats is running a sale on the high-end option from its line of wireless headphones. While the Beats Studio Pro normally retails for $250, it's going for just $170 during Prime Day. That's a hefty savings of $80, making this an attractive offer for the audiophiles.

Apple-owned Beats refreshed these headphones in 2023. That update introduced some serious upgrades that listeners have come to expect for pro-tier headsets. The Beats Studio Pro improved active noise cancellation and added the very useful transparency mode. It also introduced spatial audio with dynamic head tracking for even more immersion when you're This model also supports USB-C wired audio and 3.5mm wired audio in addition to its wireless capabilities.

This article originally appeared on Engadget at https://www.engadget.com/deals/the-beats-studio-pro-are-on-sale-for-170-this-prime-day-113043590.html?src=rss

The Sonos Era 100 speaker is down to $179 for Prime Day

The well-regarded Sonos Era 100 speaker is on sale for $179 as part of the Amazon Prime Day festivities. This is a discount of around $40, as the typical price is $219. The deal is available for both the black and white colorways.

We reviewed the Era 100 and came away impressed, saying that it provides "affordable multi-room audio that actually sounds good." This model replaced the Sonos One speaker and it's an improvement on that design in every major way. The sound quality is great and it gets plenty loud for get-togethers and the like.

The design is simple and attractive and there's both Bluetooth and line-in support. It includes built-in mics for Trueplay tuning and works with just about every music streaming service. It's a good little speaker.

While it's easy to recommend this unit, there are a couple of little caveats. It doesn't offer voice support for Google Assistant, though it does integrate with Alexa and the company's proprietary voice assistant. Also, this is a single speaker so there's no real stereo separation.

The company is also discounting the Beam 2 soundbar from $463 all the way down to $369. That's a savings of nearly $100.

This article originally appeared on Engadget at https://www.engadget.com/deals/the-sonos-era-100-speaker-is-down-to-179-for-prime-day-103041817.html?src=rss

The best Prime Day camera and drone deals: Get up to 41 percent off gear from DJI, Canon, Sony and others

If you’re in the market for a new camera, drone or accessories, Amazon’s October Prime Day is proving to be a particularly good time to shop. You can find deals from major brands including DJI, Canon, Sony, Panasonic, Nikon and others. You’ll also see discounts on important accessories like memory cards, backpacks and tripods from the likes of LowePro and SanDisk.

Many of these deals are on products that rarely go on sale, like DJI drones and Insta360 cameras, along with Canon, Nikon and Panasonic lenses. And you’ll see many products that appear in our most recent camera guide that are highly recommended by Engadget — so check that out as you add items to your cart. Now, dive in to see the best Prime Day camera deals you can find this week.

DJI Neo drone for $159 (20 percent off): The DJI Neo may be an inexpensive, beginner-friendly drone, but it has powerful features like subject tracking and quick shots. It can shoot video at up to 4K 30 fps and is quick and maneuverable, though it's also fairly loud. You can also grab one with three batteries and a charger for $229 (21 percent off).

Polaroid Now 3rd-generation plus film for $136 (15 percent off): Polaroid is a name synonymous with instant cameras, and its Now model is the best choice for larger film. With this deal, you can grab one now with film for just $7 over the price of the camera without film. 

DJI Osmo Action 4 for $229 (23 percent off): DJI's Osmo Action 4 is a solid deal at this price, as you're not giving up much in comparison to the most recent model, the Action 5. It has the same big 1/1.3-inch sensor that delivers excellent video quality, especially in low light. It also features a D-LogM profile to boost dynamic range, DJI's excellent clip-on mount and high-quality 4K 120p video.

DJI Mini 4K drone for $239 (20 percent off): The Mini 4K is a beginner-friendly drone, but it's still got plenty of nifty features. As the name suggests, it can capture 4K video at up to 30 FPS. It can also record 2.7K footage at 60 FPS. There's 2x digital zoom, a 3-axis gimbal and electrical image stabilization. The drone can transmit 1080p video from up to 10km away.

HoverAir X1 drone for $265 (34 percent off): The HoverAir X1 offers features like a folding, people-safe design, and up to 2.7K 30p HDR video. Unlike DJI’s Flip, it can dodge obstacles while tracking people, making it slightly better for that purpose. 

DJI Osmo Action 5 Pro for $269 (21 percent off): DJI's Osmo Action 5 Pro is a good alternative to GoPro's Hero 13 Black. It has a 1/1.3-inch sensor that makes it better than its rival in low light and rivals it in battery life as well with over two hours while shooting in 4K 60p. Another nice feature is 47GB of internal storage, something its main rivals lack. And the Osmo Action 5 Pro works directly with DJI’s noise-cancelling Mic 2 and Mic Mini wireless microphones, providing an easy way to record high-quality sound.

GoPro Hero 13 Black for $359 (17 percent off): GoPro’s Hero 13 Black is now available with a new family of modular lenses called the HB series (ultra-wide, anamorphic and macro), making it far more versatile for action creators. It also has a slightly bigger battery that allows longer capture times, up to 90 minutes for 4K 30fps video. Other specs remain the same, including up to 5.3K at 60fps in 10-bit color, along with the excellent Hypersmooth stabilization. And if you want an even wider field of view, grab the Hero 13 Black Wide Edition for $329

DJI Osmo 360 action cam for $413 (25 percent off): It took DJI awhile to get a panoramic action cam into the market, but the Osmo 360 was worth the wait. It stacks up well against its main rival, Insta360’s X5, by offering better video quality in low light or high-contrast situations. It’s also easy to use, offers good battery life and trumps its competition with a large amount of built-in storage.

Insta360 X5 action camera for $500 (9 percent off): The X5 has a larger 1/1.28-inch sensor compared to the X4's 1/2-inch sensor, ensuring more detail and a notable boost to low-light performance. Another key update is for PureVideo, allowing it work single lens mode rather than just in 360 mode as before.

Sony ZV-1F for $498 (17 percent off): Sony's ZV-1F is designed purely for vlogging thanks to the fixed 20mm lens that works perfectly for self-filming. It uses a 1-inch sensor like other compacts in this series and supports 4K shooting at up to 30 fps, the same as the ZV-1, and 1080p at up to an impressive 120fps. It offers vlog-ready features like background defocus and product showcase. 

Canon EOS R100 with RT-S18-45mm lens for $529 (15 percent off): Canon's EOS R100 is the only modern mirrorless camera you can get with a kit lens for under $600. It comes with a 24-megapixel APS-C sensor that delivers great picture quality with Canon's pleasing skin tones.

Canon EOS R50 with RF-S18-45mm lens $720 (18 percent off): Canon's 24-megapixel APS-C EOS R50 is great for travel, parties, street photography and more thanks to the portable size and built-in flash. It offers nice image quality with warm, human friendly photos and is capable for creators as well with 4K 30fps supersampled video, with 10-bit and HDR capability. It comes with a kit lens that's solid for vlogging or photography with a 24-70mm full-frame equivalent zoom range. 

Panasonic Lumix S9 for $1,198 (20 percent off): The S9 may be Panasonic's smallest full-frame camera but it comes with the same 24MP sensor and similar video features to the popular S5 II. To that end, it offers up to 6.2K video, in-body stabilization and reliable autofocus. The key feature though is a special LUT button that lets you easily choose a custom cinematic look designed by professional creators.

Panasonic S5 II for $1,498 (25 percent off): It’s the company’s first camera with hybrid phase-detect AF designed to make focus "wobble" and other issues a thing of the past. You can shoot sharp 4K 30p video downsampled from the full sensor width, or 4K 60p from an APS-C cropped size, all in 10-bit color. It even offers 5.9K 30p video. You also get a flip-out screen for vlogging and updated five-axis in-body stabilization that’s the best in the industry. Photo quality is also good thanks to the dual-gain 24-megapixel sensor. The main drawback is the slowish burst speeds.

Sony A7 IV for $2,198 (19 percent off): Resolution is up considerably from the 24-megapixel A7 III to 33 megapixels, with image quality much improved overall. Video is now up to par with rivals with 4K at up to 60p with 10 bit 4:2:2 quality. Autofocus is incredible for both video and stills, and the in-body stabilization does a good job. The biggest drawback is rolling shutter that limits the use of the electronic shutter.

Panasonic S5 IIx with two lenses for $2,298 (22 percent off): The S5 IIx is identical to the S5 II except that it offers high bitrate Apple ProRes capture directly to an external SSD. This deal is ideal for creators who want to hit the ground running as it includes both a 50mm f/1.8 portrait lens and a 22-60mm zoom. 

Nikon Z6 III for $2,397 (11 percent off): Nikon's Z6 III is the best hybrid mirrorless camera for the money, thanks to the incredible performance of the 24-megapixel partially stacked sensor. You can shoot RAW bursts at up to 20 fps in electronic shutter mode while nailing sharp shots thanks to the much-improved autofocus. On the video side, it supports 6K RAW at up to 60 fps, or 4K 120p. All of that makes it ideal for creators and photographers alike, with the only drawback being the reduced resolution.

Sony A7R V for $3,798 (10 percent off): With a 61-megapixel sensor, the A7R V shoots sharp and beautiful images at a very respectable speed for such a high-resolution model (10 fps). It has equally fast and reliable autofocus, the sharpest viewfinder on the market and in-body stabilization that’s much improved over the A7R IV. Video has even improved, with 8K and 10-bit options now on tap, albeit with significant rolling shutter

Osmo Mobile 7 for $75 (16 percent off): One of the best things to elevate your smartphone footage is a gimbal like the Osmo Mobile 7 from DJI. The company makes some of the best drones you can buy, so it knows a thing or two about camera stabilization, so it will make your smarphone videos smooth as silk. It only weighs 300 grams, so it’ll be a lightweight addition to almost any travel kit.

K&F Concept 20L camera backpack for $66 (20 percent off): This multifunction backpack can store not only cameras, lenses and even drones in the bottom section, but a couple of changes of clothes up top. It has a laptop compartment, ventilated elastic back, auxiliary straps and more.  

DJI Mic Mini $99 (41 percent off): DJI's Mic Mini bundle includes two mic transmitters and a receiver that can be connected to a camera or phone, along with a charging case. The mics weigh just a third of an ounce and attach easily to subjects via magnets or clips. Everything pairs automatically and they offer high quality 24-bit 20Hz to 20K Hz recording. They also connect easily to smartphones over Bluetooth and other DJI devices like the Action 5 and Osmo Pocket 3 cams using DJI's OsmoAudio direct connection. 

SmallRig Camera Tripod for $49 (30 percent off): This 2-in-1 tripod easily transforms into a monopod depending on your needs. It comes with a 360-degree detachable ball head, supports up to 33 pounds and lets you adjust the working height from 16- to 71-inches in seconds. 

Rode Wireless Micro for $99 (24 percent off): Another great wireless mic option is Rode's Wireless Micro designed for smartphone users. The receiver connects to the bottom of your smartphone via USB-C and the microphones attach to the subject via integrated clips or magnets. They capture pristine sound well above what your smartphone can do, with a 20-20 kHz frequency range and 73 dB signal-to-noise ratio.

SanDisk 512GB Extreme Pro CFexpress Card Type B for $120 (24 percent off): If you need tons of storage for a newer camera with a CFexpress Type B slot, SanDisk's 512GB is a great deal. It can handle reading and writing at 1,700MB/s and 1,400MB/s respectively, enough speed for RAW video capture. 

Lowepro Flipside BP 300 AW III for $182 (24 percent off): The Flipside BP300 AW III is a rugged, lightweight bag that securely holds and protects your camera gear in the worst weather. It has rear access for protection and a special compartment to hold lenses. 

SmallRig AD-80 FreeBlazer video tripod for $175 (30 percent off): Weighing just 11.6 pounds, it supports up to a 17.6-pound load and expands from 34 to 75 inches with a one-step height adjustment. For smooth operation, it offers fluid head damping though 360-degree horizontal and +90°/-65° tilt. 

DJI Mic 2 for $269 (23 percent off): DJI's Mic 2 can not only be connected to a mirrorless camera like other mics, but also supports Bluetooth audio so can easily be connected to a smartphone as well. It picks up audio from your subject at a range of up to 820 feet (less with a Bluetooth connection) and automatically reduces background noise like wind, city sounds and even drone noise. This deal includes two mic transmitters, a receiver for your camera, a charging case and wind muffs. 

DJI RS 4 Mini $309 (16 percent off): The RS 4 Mini is one of the best handheld camera stabilizers on the market thanks to features like its 4.4 pound payload and automatic axis lock. On top of that, the company introduced automatic tracking via its RS Intelligent Tracking Module to keep human subjects in frame no matter where they go. It also offers smoother gimbal tracking, longer battery life and faster charging. 

Lexar 128GB Professional 2000x SD Card $90 (31 percent off): If you need very fast SD UHS II memory, Lexar currently has an excellent deal on its 128GB 2000x memory card. It offers 300MB/s read and 260Mb/s write speeds, quick enough to capture high data rate video or bursts of high-resolution photos. Amazon is also offering a solid discount on 256GB memory in the same lineup at $170 or 23 percent off

Manfrotto Befree GT PRO 4-section travel tripod $299 (36 percent off): Belying its miniscule 4.23 pound weight, this model offers ultra-stable performance for timelapse and other shots, even in bad weather. It's also great for video thanks to the integrated 3-way pan/tilt head, featuring fluid cartridges for precise control and seamless movements.

Panasonic Lumix G 25mm f/1.7 lens $248 (17 percent off): Panasonic and Micro Four Thirds users on a budget in need of a fast 50mm equivalent prime should check this one out. It offers beautiful bokeh and fast speeds in low light, but costs nearly half the price of f/1.4 models. 

Nikon Nikkor Z 50mm f/1.4 Lens $497 (17 percent off): If you want a fast 50mm portrait lens but don't have a ton to spend, Nikon's Nikkor Z 50mm f/1.4 lens is on sale for just $497, making it one of the cheapest full-frame options available. At the same time, it offers exceptional sharpness and excellent color rendition, with beautiful bokeh that will flatter your subjects. 

Panasonic Lumix S 85mm f/1.8 lens $448 (31 percent off): I own this lens and it's fast, sharp and versatile for portraits while offering considerable savings compared to an f/1.4 portrait. It's also great for working pros due to the dust-, splash- and freeze-resistant design and very light weight next to other brands. 

Nikon Nikkor Z 35mm f/1.4 Lens $577 (15 percent off): If you're looking for a fast full-frame Nikon Z prime in the 35-50mm category for portraits, architecture or street photos, Nikon has a stellar deal. The Nikkor Z 35mm f/1.4 lens is fast and sharp with painterly bokeh thanks to the 9-blade iris design. It's great for video as well, with the silent STM mechanism offering silent autofocus and suppressed focus breathing.

Canon RF24-70mm F2.8 L lens $2,399 (8 percent off): If you've been eyeballing a fast Canon RF mount zoom, now's the time to act. The RF24-70mm f/2.8 L lens rarely goes on sale, but is now available with a $200 (8 percent) discount. It offers an f/2.8 aperture across the entire zoom range so you get awesome bokeh for portraits and high versatility in low light situations. 

This article originally appeared on Engadget at https://www.engadget.com/cameras/the-best-prime-day-camera-and-drone-deals-get-up-to-41-percent-off-gear-from-dji-canon-sony-and-others-073852143.html?src=rss

Clair Obscur: Expedition 33 has sold five million copies

The French RPG Clair Obscur: Expedition 33 has officially sold five million copies across all platforms. That's a fantastic metric for an original IP, even one that has garnered stellar reviews.

Developer Sandfall Interactive is currently prepping a fairly substantial update as a "thank you" to fans, according to a report by Eurogamer. There's no release date yet on this, but it will be free DLC. We also know there will be a new story that focuses on the fan favorite character Esquie.

The update will include new boss battles, a brand-new location, updated costumes for all party members and "even more surprises fans can look forward to." Finally, there will be some quality-of-life additions and localization to several new languages.

"We want to prepare an update to say a big thank you to our players, because it's thanks to our players that we are in such a comfortable situation now," game director Guillaume Broche said. "They brought us so much emotion and gave us so much love in return for the game that we want to address that and make a big thank you update with new content, new enemies, new stuff to do for every type of player."

For the uninitiated, Clair Obscur: Expedition 33 is a well-regarded RPG that we called "a beautiful game with dramatic heft and satisfying combat." It features some well-known voice actors, including Charlie Cox and Andy Serkis.

This article originally appeared on Engadget at https://www.engadget.com/gaming/clair-obscur-expedition-33-has-sold-five-million-copies-153148952.html?src=rss

Google's Pixel Buds Pro 2 are cheaper than ever for Prime Day

The unfortunate reality of living in a world that's largely abandoned headphone jacks is that you have to own a pair of wireless earbuds to listen to things on your phone. Accepting that, you might as well own a good pair of earbuds, and if you're on Android, Google's wireless earbuds are one of your best options. You can purchase a pair of Google's Pixel Buds Pro 2 for $170 for Prime Day, $60 less than its normal $230 price. That's a pretty great deal for a pair of wireless earbuds that rival Apple's AirPods Pro 3.

The Pixel Buds Pro 2 are compact wireless earbuds with a touch-sensitive surface and a small circular ring in the back to help them stay in your ears. You can currently purchase the buds in bluish-gray "Moonstone," off-white "Porcelain," pink "Peony" or light black "Hazel" color options, but whichever you choose, you'll get solid active noise cancellation and a collection of other helpful audio features.

In terms of ANC, Engadget's review of the Pixel Buds Pro 2 found that the earbuds do a good job of blocking out "low-to-mid-range noise" but still struggle to block out nearby voices. On the whole, though, the Pixel Buds Pro 2 sounds better than Google's previous wireless earbuds, particularly when you're listening bass-forward tracks.

The capabilities of the Pixel Buds Pro 2 extend beyond just listening to music, of course. Like its competitors, Google has turned its wireless earbuds into hearing protection, too. The Pixel Buds Pro 2 were recently updated to support what Google calls Loud Noise Protection, which can reduce incoming loud noises to protect your ears. That's on top of features like Adaptive Audio, which can adjust noise cancellation and volume based on your surroundings, and Talk to Gemini Live, which gives you a hands-free way to have a free-flowing conversation with Google's AI chatbot.

There might be other earbuds that offer better audio performance, but the Pixel Buds Pro 2 is the best option if you're on Android and want a seamless experience. For $170 during Prime Day, that's hard to pass up.

This article originally appeared on Engadget at https://www.engadget.com/deals/googles-pixel-buds-pro-2-are-cheaper-than-ever-for-prime-day-130038433.html?src=rss

Amazon will start dispensing prescription drugs through vending machines

Amazon’s quest to become a genuine all-in-one healthcare solution has already seen it commit to same-day prescription deliveries, but visitors to its One Medical offices can now pick up their medication from a vending machine right after an appointment.

Amazon Pharmacy Kiosks will start rolling out in December, initially in One Medical practices in the greater Los Angeles area, with plans already in place for an expansion into other locations in the near future. Amazon says it intends to combat the high percentage of people who never file their prescriptions by making them immediately available at the point of care. The idea is that if people don’t need to make a separate trip to a dedicated pharmacy to pick up their prescription drugs, they’re more likely to get them, while clinicians won’t have to worry about their patients’ conditions going untreated.

One Medical customers can request pickup for a prescription at an on-site Amazon Pharmacy Kiosk in the Amazon app as soon as it’s handed to them, with the company promising that most medications will be available to collect within minutes. You’ll need to already have an Amazon Pharmacy account and attend an appointment at a participating One Medical location to make use of the service.

Upfront costs and any available deductions will be displayed in the Amazon app before you check out, and if needed you can also connect to an Amazon Pharmacy pharmacist via the app for a video or phone consultation. Medications that will be stored in the vending machines include antibiotics, inhalers and blood pressure medications, but not controlled substances or anything that requires refrigeration.

One Medical subscriptions usually cost $9 per month of $99 annually for Prime members, or $199 for everyone else, although Amazon is currently offering memberships to its Prime customers for $30 off. You can also schedule virtual appointments for a one-off fee without a membership, but to use an Amazon Pharmacy Kiosk during the launch period you’ll need to visit an in-person One Medical office. Amazon says there won’t be any added fees to use the machines, whether you’re a Prime member or not.

This article originally appeared on Engadget at https://www.engadget.com/big-tech/amazon-will-start-dispensing-prescription-drugs-through-vending-machines-144555105.html?src=rss

This Prime Day iPad deal brings the iPad A16 down to a record low for Amazon's October sale

The entry-level Apple iPad with the A16 chip is on sale for $280 as a Prime Day promotion. This is a discount of around $70 and represents a record-low price for the 11-inch tablet. The deal is available in multiple colorways and is one of the best Apple deals for Prime Day this year.

This tablet made our list of the best iPads and we particularly recommend it for the budget-conscious. It may lack some of the bells and whistles of its more expensive cousins, but it still gets the job done. It's fast enough for most common tasks and the battery life is solid, at 10 hours per charge. It also ships with 6GB of RAM, which is a decent enough metric.

The tablet integrates with Wi-Fi 6 and features a USB-C connector, along with a pair of 12MP cameras. There's also a Touch ID sensor, which can be used to unlock the device and to make payments.

This is the most basic tablet in Apple's lineup, so it lacks some features. It doesn't integrate with the Apple Pencil Pro or the Magic Keyboard. The display is also not quite as gorgeous as the iPad Air or Pro, but it's still a Liquid Retina panel. 

Elsewhere among the Apple deals for Prime Day, you can get $150 off the iPad Air — both the 11-inch model and the 13-inch model.

This article originally appeared on Engadget at https://www.engadget.com/deals/this-prime-day-ipad-deal-brings-the-ipad-a16-down-to-a-record-low-for-amazons-october-sale-082743171.html?src=rss

Prime Day deals include the Google Pixel 9a for a new record low, plus discounts on Pixel 10 phones

At its typical $499, the Google Pixel 9a is Engadget's pick for the best midrange phone. But when it's $150 off, you'll be hard-pressed to find a better deal on any piece of tech. Right now, you can get Google's budget-friendly phone for a record-low $349 thanks to Amazon Prime Day.

The Pixel 9a may lack the cutting-edge sizzle of ultra-premium phones that cost triple what you'll pay here. But in return, you get strong performance, a sleek design, a robust battery that lasts over 28 hours and camera quality that rivals that of competitors costing $1,000 or more.

The phone has a simple design with an aluminum frame and a recycled polycarbonate back. It has an IP68 rating for solid protection against dust and water. On the front, you have a spacious 6.3-inch OLED display with a 120Hz refresh rate. The screen's brightness can reach an impressive 2,700 nits, matching the standard Pixel 9. Its resolution is a crisp 1080 x 2424 (422 PPI).

In Engadget's tests, the Pixel 9a's camera "preserved more details and produced a generally better-looking image" than the Galaxy S25 Ultra's. (If you aren't familiar, that's a $1,300 phone.) The Pixel 9a does lack a dedicated telephoto lens. But Google has included the Super Res Zoom AI upscaling feature to help compensate for the loss.

Amazon's deal includes all four colors available for the phone: obsidian, porcelain, peony and iris. There's no guarantee stock will last through all of October Prime Day, so you may want to consider pouncing soon if this deal is for you. Also on sale are the Pixel 10 and Pixel 10 Pro, which you can pick up for $$649 and $799, respectively.

This article originally appeared on Engadget at https://www.engadget.com/deals/prime-day-deals-include-the-google-pixel-9a-for-a-new-record-low-plus-discounts-on-pixel-10-phones-120044715.html?src=rss

The Sony WH-1000XM6 headphones are $20 off for Prime Day

October Prime Day has Engadget's favorite wireless headphones on sale. You can get Sony's excellent WH-1000XM6 for $20 off. While that's far from the steepest tech discount you'll see this week, it's a record low for this product. (After all, Sony only launched the XM6 in March, so this is still new gear.) You can get them today for $430.

The WH-1000XM6 takes a leap forward in sound quality, active noise cancellation (ANC) and other features. Our audio reviewer, Billy Steele, called them the best headphones you can buy right now. "The crown is safe once again," he wrote. "Sony has managed to overhaul its flagship headphones in all the right ways that keep the 1000X line atop our best headphones list."

The XM6 has a powerful new chip, the QN3, that unlocks much of its potential. Sony also developed new drivers for this model, resulting in richer details, clearer vocals and a better overall balance. The headphones added four extra microphones to enhance ANC. The XM6 is especially improved at blocking out voices.

If you're a fan of spatial effects, which simulate a wider soundstage, Sony added that for this generation. The (optional) 360 Spatial Sound feature transforms regular stereo content into something with a surround-sound effect. It's similar to what Apple and Bose have in their models. It's yet another audio effect option in Sony's app, alongside 360 Reality Audio and DSEE Extreme upscaling.

The headphones are no slouch in the battery life department. The XM6 is rated for up to 30 hours with ANC on and up to 40 hours with it off. In Engadget's testing, we had no problem hitting those advertised figures.

If you'd rather save more money for a lesser (but still great) pair of cans, Sony's last-gen model is also on sale. You can get the WH-1000XM5 for $100 off. The 2022 flagship headphones offer premium sound, ANC, and battery life. Typically $400, you can get them during October Prime Day for $298.

This article originally appeared on Engadget at https://www.engadget.com/deals/the-sony-wh-1000xm6-headphones-are-20-off-for-prime-day-094527714.html?src=rss

Nintendo's mystery animated short is, in fact, for a Pikmin project

Nintendo has released a second version of the animated short that confused many fans and is now likely to have made some of those who guessed what was going on feeling very pleased with themselves. The video appears to be the same as the one that the company foisted upon the world on Tuesday, but there’s one critical difference. This time, you can more clearly see Pikmin moving a baby’s building blocks and pacifier around its bedroom.

The little creatures were invisible in the first version of the video for the most part, though there was an out-of-focus one running underneath the tot’s crib. Well done you, if you spotted that, or noticed the nods to Pikmin music in the short’s score.

According to the Pikmin Bloom mobile game, Pikmin are invisible to humans, which is likely why the tot’s mother doesn’t react to them here. The parent is probably more interested in her kiddo’s apparent first steps than how the pacifier got caught in the mobile above the crib, anyway.

As with the first version of the short, the updated video first appeared in the Nintendo Today app — we’ll update this story to include a version from elsewhere once it’s available. Nintendo clearly really wants fans to use that to get major announcements from the company first.

Being able to see the Pikmin in all their glory this time around does clear up one key question about the initial short (which is now even more adorable), but another one remains. Just what the heck is Nintendo actually teasing here? It’s unclear whether the company has a new Pikmin game up its sleeve or whether it’s making a movie about the lil’ critters. It could be something else entirely! Perhaps another version of the short is coming to clear that up.

This article originally appeared on Engadget at https://www.engadget.com/nintendos-mystery-animated-short-is-in-fact-for-a-pikmin-project-135410770.html?src=rss

Get 40 percent off this Roomba robot vacuum for Prime Day

Robot vacuums are great items to look for during events like October Prime Day. They're usually hundreds of dollars off, so you can save a ton if you're buying one as a gift or you want to upgrade an aging robovac you have at home already. One of the best deals this time around is on the iRobot Roomba 104, which is 40 percent off and on sale for only $150.

This is a newer version of the unit that topped our list of the best budget robot vacuums. It's an entry-level robovac that gets the job done. The cleaning motor is fairly powerful and it ships with a multi-surface brush and an edge-sweeping brush. The vacuum uses LiDAR to map a home and to help it avoid obstacles when cleaning.

It's also been equipped with specialized sensors to prevent falling down stairs. Steps are the natural enemy of all robot vacuums, except maybe this one. The Roomba 104 integrates with the company's proprietary app, which allows for custom cleaning schedules and the like. The robot can also be controlled via voice assistant and boasts compatibility with Siri, Alexa and Google Assistant.

The vacuum will automatically head to the charger for some juice when running low, which is nice. The battery lasts around 200 minutes per charge, which is a decent enough metric for a budget-friendly robovac. The only downside here? This is just a vacuum. It doesn't mop and it doesn't come with a dedicated debris canister.

This article originally appeared on Engadget at https://www.engadget.com/deals/get-40-percent-off-this-roomba-robot-vacuum-for-prime-day-164953827.html?src=rss

Anker's latest Prime charging devices are up to 27 percent off for Prime Day

Anker's latest Prime charging devices are already on sale thanks to Prime Day discounts. The best deals include the laptop-compatible Prime Power Bank (26,250mAh, 300W), which is $60 off and down to $170.

This portable charger delivers a whopping 300W of total output between its two USB-C ports and single USB-A port. Anker says that, thanks to its 140W output (and if you're using a 5A cable), you can top up the battery of an M4 Pro MacBook Pro to 50 percent in 27 minutes and an iPhone 17 Pro Max to 50 percent in 22 minutes. You can keep tabs on what's happening on each port using the display.

This is also the first Anker power bank that supports up to 250W of input recharging by using both USB-C ports simultaneously. This faster charging can top up the powerbank's own battery to 50 percent in just 13 minutes, according to Anker.

This model has a capacity of 26,250mAh (99.75Wh), which is very close to the FAA's limit of 100W. It's TSA-approved, so you'll be able to take it on flights. It's capable of taking an M4 MacBook Pro from fully dead to an 80 percent charge. The power bank weighs 1.3 lbs — the same as about three iPhones, Anker says.

Other Anker Prime devices are on sale too. A new 3-in-1 MagSafe charger — which can top up the batteries of your iPhone, Apple Watch and AirPods with wireless charging case simultaneously — also has a $58 discount to $172 . While there are certainly less expensive 3-in-1 MagSafe options out there, this one includes Qi2 25W support for faster charging, as well as TEC active cooling. Anker suggests this can help speed up charging times and help guard against iPhone battery degradation over time.

A three-port GaN Prime Charger that plugs into an outlet is $40 off too, now down to $110. Anker says it's as compact as an AirPods Pro 3 case and can provide a total output of 160W, with up to 140W via a single USB-C cable. The charger is said to offer smart power distribution, and you can monitor what's happening and adjust modes via an onboard display and controls.

This article originally appeared on Engadget at https://www.engadget.com/deals/ankers-latest-prime-charging-devices-are-up-to-27-percent-off-for-prime-day-152040343.html?src=rss

Prime Day deal: The Amazon Echo Spot alarm clock drops to $45

Amazon may have announced new Echo Show devices recently, but it didn't touch the humble Echo Spot. The smart alarm clock remains the smallest Echo device with a display, but it's one that's really best just for showing the time, weather and other quick bits of information. You can grab one now for only $45 thanks to Prime Day deals; that's 44 percent off its usual price.

The latest incarnation of the diminutive Spot was introduced in July 2024, and this matches its record-low price. For that you get a comfortably bedside-sized device with a sharper display than its predecessor, as well as superior sound. The front face is divided into two halves, with a speaker positioned below the hemispherical display.

What screen you do have is more than enough to display the time and weather information, plus it can show you the song or album title and accompanying artwork when you’re listening to music on those improved speakers. It can naturally be used to boss around your other connected smart devices, too.

Alexa might be baked in, but the Echo Spot is intended to be a fairly bare-bones smart alarm clock, so don’t expect as many features as you’ll find on something like the Echo Show 5. But a lot of people just want a modern alarm clock, and arguably the biggest selling point for the Echo Spot is its total lack of a camera. While that means it can do less than the original 2017 Echo Spot, which Amazon did put a camera in, the decision to remove it from a device that lives right next to your bed was probably for the best.

Amazon’s Prime Day sale returns on October 7, so you can expect a range of deals on its various Echo devices. For our guide to all of the best early deals, head here.

This article originally appeared on Engadget at https://www.engadget.com/deals/prime-day-deal-the-amazon-echo-spot-alarm-clock-drops-to-45-142550337.html?src=rss

A bundle of two Blink Mini 2 cameras is only $35 this Prime Day

October Prime Day is here and you can grab record-low prices on a bunch of our favorite tech. Blink security cameras are almost always on sale during Amazon's shopping events, and this time is no different. One of the best deals at the moment is on a duo of Blink Mini 2 cameras, which you can get for only $35. That's half off and a record-low price, not to mention less than what you'd typically pay for one full price. It's also Engadget's pick for the best budget security camera.

This budget-friend, wired camera is well-suited for nighttime video: It has a built-in LED spotlight, color night vision and a low-light sensor. Day or night, it records in sharp 1080p resolution. It also has a wider field of view than its predecessor.

The Blink Mini 2 is primarily designed for indoor use. But you can use it outdoors, too. You'll just need to fork over $10 for a weather-resistant adapter. Wherever you use the camera, it works with Alexa and supports two-way audio. ("Hello, doggy, I'll be home soon.")

It also supports person detection. (That's a neat feature that differentiates between people and other types of movement.) However, the feature requires a Blink Subscription Plan. They start at $3 per month or $30 per year for one device.

The camera is available in black or white. Both colors are available for the $35 Prime Day deal, but they can't be mixed unless you buy each separately. It's worth noting that this deal is open to anyone — no Prime subscription necessary. Amazon recently announced an upgraded version of this camera that supports 2K video, but it won't be available until later in October.

You can also save on a bunch of other Blink (and Ring) security gear for Prime Day. The Blink Outdoor 4 cameras are some of our favorites, and most configurations are on sale for Prime Day, including bundles like this three-camera system that's 61 percent off.

This article originally appeared on Engadget at https://www.engadget.com/deals/a-bundle-of-two-blink-mini-2-cameras-is-only-35-this-prime-day-201049070.html?src=rss

This Ninja dual-zone air fryer is 30 percent off for Prime Day

Amazon Prime Day is already half over, and there are deals running on everything from electronics to kitchen appliances. The latter includes a sale on Ninja's DZ302 10-quart Air Fryer with Dual Baskets, dropping its price from $230 to $160. The 30 percent discount brings the air fryer's price to just $10 more than its all-time low.

The 10-quart Ninja DZ302 Air Fryer is a great investment for a lot of reasons, starting with its six settings. You can use it to air fry, air broil, bake, dehydrate, keep things warm and roast your food. Even better? It has two five-quart baskets that allow you to cook two different foods at two different settings. Also, despite it's capabilities, at under 15 inches, it doesn't take up too much counter top real estate (though it's probably too large for the smallest kitchens). 

The air fryer also comes with Ninja's Smart Finish feature, which ensures your two foods finish cooking at the same time. Plus, there's the Match Cook option which sets both baskets to the same instructions for when you're cooking one thing across both.

Those two features are the main difference between the Ninja DZ302 and the 10-quart Ninja DZ401 Foodi — our pick for best dual-zone air fryer. But, otherwise, the latter will give you a very similar device for $130.  

This article originally appeared on Engadget at https://www.engadget.com/deals/this-ninja-dual-zone-air-fryer-is-30-percent-off-for-prime-day-110026266.html?src=rss


From Chaos To Clarity: How B2B Marketing Leaders Can Organize AI Responsibilities For Business Impact

In the rush to adopt AI, many marketing leaders assign resources on the fly, without a formal structure or accountability. This “just in time” approach may feel agile — but it creates silos, duplicates effort, and introduces governance risks.

Predictions 2026: AI Moves From Hype To Hard Hat Work

In 2026, AI will trade its tiara for a hard hat as enterprises prioritize AI function over flair. This year’s AI predictions emphasize the importance of investing in areas such as training and governance while evaluating the ROI of AI more closely.


Google Search AI Mode is available in 36 new languages and 45 regions

Google has announced that it has expanded AI Mode in Search to more regions, and has added support for several new languages. It will roll out to more users next week. Oddly, […]

Thank you for being a Ghacks reader. The post Google Search AI Mode is available in 36 new languages and 45 regions appeared first on gHacks Technology News.

Apple takes a swipe at Windows with a BSOD-focused ad

Apple has uploaded a video on YouTube to mock Windows. It is related to last year's CrowdStrike fiasco that took down millions of PCs worldwide. The 8-minute-long video focuses on The Underdogs, […]

Thank you for being a Ghacks reader. The post Apple takes a swipe at Windows with a BSOD-focused ad appeared first on gHacks Technology News.


Is the Massive Forehead of This Human Pennywise Figure a ‘Welcome to Derry’ Spoiler?

Pennywisebaldcropped

NECA's new tie-in figure for the HBO 'It' prequel hints at a whole new side of the demonic clown.

What We Know About the Biggest Unseen War of ‘Star Trek’

Star Trek Earth Romulan War Balance Of Terror Kirk Commander

The Earth-Romulan War is a major cornerstone of 'Star Trek' history—but it's also 'Star Trek' history that's largely kept it off our screens for almost 60 years.

Disney’s Rough Time Gets Rougher

Zootopia Animal Kingdom Disney Experiences

Park price hikes and an unfortunate death at Disneyland continue the company's string of bad news—but it's not all bad.

Is the Founder of Polymarket Really the Youngest Self-Made Billionaire?

Polymarketcoplan

Shayne Coplan is having a good year.

Jason Blum Missed Out on ‘Texas Chain Saw’ But He’s Still Got High Horror Hopes

Sawx

The head of Blumhouse discusses his plans for 'Saw' and other franchises he'd like to sink his teeth into.

iOS 26 Just Made Driving Like an Asshole a Lot Easier

Apple AirPods Pro 3 Review 5

Want to keep your AirPods in while driving? iOS 26 has your reckless back.

‘Sanda’ Is a Weird, Wild, and Wonderfully Unhinged Holiday Horror-Comedy Anime

Sanda Science Saru Anime Io9 2025 Review

The premiere episode of Science Saru's 'Sanda,' from 'Beastars' creator Paru Itagaki, is a delightfully deranged Halloween-meets-Christmas gift that keeps on giving.

Uber Driver Who Allegedly Caused the Palisades Fire Used ChatGPT to Imagine a Forest Burning

Jonathan Rinderknecht Chatgpt

The suspect asked ChatGPT to create a "dystopian painting" months earlier.

Scientists Just Solved One of the Most Enduring Mysteries of the Easter Island Statues

Moai,statues,in,the,rano,raraku,volcano,in,easter,island,

The "walking moai hypothesis" could end a long-time debate over how ancient engineers moved these iconic statues around Easter Island.

You Can’t Use Copyrighted Characters in OpenAI’s Sora Anymore and People Are Freaking Out

Sora Nintendo Openai

Turns out a lot of people's creativity is limited to what someone else has already made.

As Trump Bleeds Public TV Dry, Bob Ross Paintings Go Up for Auction to Support Local Stations

Bob Ross

The work of a public media icon will go towards helping public media stations in their hour of need.

‘The Dark Crystal’ Returns to Theaters and Brian Henson Talks Its Lasting Impact

Dark Crystal Interview

The chairman of the Jim Henson Company spoke to io9 about the 4K Fathom re-release happening October 12-13.

Elon Musk’s SpaceX Is Taking More Control of the Texas Coastline Ahead of Starship’s Next Launch

SpaceX Starbase in Boca Chica, Texas

Elon Musk's newly inaugurated space city was handed control over a piece of Boca Chica beach.

Fake Protest Videos Are the Latest AI Slop to Go Viral in MAGA World

Screenshots from two viral AI-generated videos depicting protesters getting blasted with chemical agents.

Trump supporters are doubling down on AI sadism.

Trump Is Weighing Billions More in Cuts to Clean Energy Projects. Here’s What’s at Stake

President Donald Trump speaks to members of the media on the South Lawn of the White House before boarding Marine One in Washington, DC, US, on Sunday, Oct. 5, 2025.

Last week, the administration nixed more than $7.5 billion in clean energy project funding. New reports suggest that’s just the tip of the iceberg.

Oh No, the New ‘TMNT: Mutant Mayhem’ Short Turns Donnie Into a ChatGPT Stan

Teenage Mutant Ninja Turtles Chrome Alone 2 Paramount (1) 2

Thankfully, he comes to his senses by the end of the footage's clever diss on derivative, artless AI slop.

Google Pixel Buds 2a Review: A Better Value, but Nothing Mind-Blowing

Google Pixel Buds 2a Review 09

Google's new lower-cost wireless earbuds bring more value than before, but the competition offers even more at the same price or less.

Google Pixel 10 Pro Fold Review: Not Enough When Samsung’s Galaxy Z Fold 7 Exists

Google Pixel 10 Pro Fold Watch 4 50

Even with AI, Google's third-gen foldable can't clear the Z Fold 7 bar.

‘The Lost Boys’ Broadway Musical Is Actually Happening

The Lost Boys Poster

Based on the hit 1987 vampire movie starring Kiefer Sutherland, the musical just announced its opening date and main cast.

Nobel Prizes: 5 Unlikely Winner Reactions, From the Unbothered to the Downright Mad

Doris Lessing Nobel Prize Reaction

Apparently people just have better things to do than win the world's most prestigious prize.


Escaping Prototype Purgatory: A Playbook for AI Teams

We’re living through a peculiar moment in AI development. On one hand, the demos are spectacular: agents that reason and plan with apparent ease, models that compose original songs from a text prompt, and research tools that produce detailed reports in minutes. Yet many AI teams find themselves trapped in “prototype purgatory,” where impressive proofs-of-conceptContinue reading "Escaping Prototype Purgatory: A Playbook for AI Teams"

The post Escaping Prototype Purgatory: A Playbook for AI Teams appeared first on Gradient Flow.


Was The Dead Internet Theory Only a Theory?

In 2016 the world changed, timelines that were once filled with real conversations have been quietly replaced by recycled opinions, trending hashtags, and algorithmically sculpted outrage. Around 2019, users on boards like Wizardchan and 4chan’s /x/ (the paranormal board) started posting that the internet no longer felt alive.

Read All

Miggo Security Named a Gartner® Cool Vendor in AI Security

Miggo Security has been recognized as a Gartner Cool Vendor in AI Security. Miggo’s predictive analysis, preemptive protection, and real-time response is built specifically for the risks of AI-driven environments.

Read All

The Sales Whisperer® on AI, Automation, and the Future of Selling: A Conversation with Wes Schaeffer

Wes Schaeffer is the host of The BJJ and Biz Podcast. He talks about how to sell smarter, automate ethically, and never lose the human element.

Read All

Inside OpenxAI: Founder Ashton Hettiarachi on the Mission to Decentralize and Democratize AI

OpenxAI is the first peer-to-peer permissionless AI protocol. Anyone can host an AI agent or application, own the entire infrastructure and application layer. The only person who can alter, update, or delete is the user. There are no middlemen or centralized choke points.

Read All


Understanding Low-Code and No-Code for Healthcare

With the high demands of software development and a shortage of developers, healthcare organizations need a fast and easy way to build software applications. Low-code and no-code software tools can speed up workflows while keeping applications HIPAAcompliant. No-code includes methods such as drag-and-drop, while low-code incorporates a small amount of coding. Gartner had forecast that 70% of new enterprise applications would be built using low-code or no-code platforms by 2025, an increase from less than 25% in 2020. “LCNC platforms allow clinicians, administrators and operational staff to…


Fast, Tiny, and Smart AI: Small Language Models for Your Phone



While most of the AI world is racing to build ever-bigger language models like OpenAI’s GPT-5 and Anthropic’s Claude Sonnet 4.5, the Israeli AI startup AI21 is taking a different path.

AI21 has just unveiled Jamba Reasoning 3B, a 3-billion-parameter model. This compact, open-source model can handle massive context windows of 250,000 tokens (meaning that it can “remember” and reason over much more text than typical language models) and can run at high speed, even on consumer devices. The launch highlights a growing shift: smaller, more efficient models could shape the future of AI just as much as raw scale.

“We believe in a more decentralized future for AI—one where not everything runs in massive data centers,” says Ori Goshen, Co-CEO of AI21, in an interview with IEEE Spectrum. “Large models will still play a role, but small, powerful models running on devices will have a significant impact” on both the future and the economics of AI, he says. Jamba is built for developers who want to create edge-AI applications and specialized systems that run efficiently on-device.

AI21’s Jamba Reasoning 3B is designed to handle long sequences of text and challenging tasks like math, coding, and logical reasoning—all while running with impressive speed on everyday devices like laptops and mobile phones. Jamba Reasoning 3B can also work in a hybrid setup: simple jobs are handled locally by the device, while heavier problems get sent to powerful cloud servers. According to AI21, this smarter routing could dramatically cut AI infrastructure costs for certain workloads—potentially by an order of magnitude.

With 3 billion parameters, Jamba Reasoning 3B is tiny by today’s AI standards. Models like GPT-5 or Claude run well past 100 billion parameters, and even smaller models, such as Llama 3 (8B) or Mistral (7B), are more than twice the size of AI21’s model, Goshen notes.

That compact size makes it more remarkable that AI21’s model can handle a context window of 250,000 tokens on consumer devices. Some proprietary models, like GPT-5, offer even longer context windows, but Jamba sets a new high-water mark among open-source models. The previous open-model record of 128,000 tokens was held by Meta’s Llama 3.2 (3B), Microsoft’s Phi-4 Mini, and DeepSeek R1, which are all much larger models. Jamba Reasoning 3B can process more than 17 tokens per second even when working at full capacity—that is, with extremely long inputs that use its full 250,000-token context window. Many other models slow down or struggle once their input length exceeds 100,000 tokens.

Goshen explains that the model is built on an architecture called Jamba, which combines two types of neural network designs: transformer layers, familiar from other large language models, and Mamba layers, which are designed to be more memory-efficient. This hybrid design enables the model to handle long documents, large codebases, and other extensive inputs directly on a laptop or phone—using about one-tenth the memory of traditional transformers. Goshen says the model runs much faster than traditional transformers because it relies less on a memory component called the KV cache, which can slow down processing as inputs get longer.

The model’s hybrid architecture gives it an advantage in both speed and memory efficiency, even with very long inputs, confirms a software engineer who works in the LLM industry. The engineer requested anonymity because they’re not authorized to comment on other companies’ models. As more users run generative AI locally on laptops, models need to handle long context lengths quickly without consuming too much memory. At 3 billion parameters, Jamba meets these requirements, says the engineer, making it a model that’s optimized for on-device use.

Jamba Reasoning 3B is open source under the permissive Apache 2.0 license and available on popular platforms such as Hugging Face and LM Studio. The release also comes with instructions for fine-tuning the model through an open-source reinforcement-learning platform (called VERL), making it easier and more affordable for developers to adapt the model for their own tasks.

“Jamba Reasoning 3B marks the beginning of a family of small, efficient reasoning models,” Goshen said. “Scaling down enables decentralization, personalization, and cost efficiency. Instead of relying on expensive GPUs in data centers, individuals and enterprises can run their own models on devices. That unlocks new economics and broader accessibility.”


IBM Releases Granite-Docling-258M, a Compact Vision-Language Model for Precise Document Conversion

IBM Research has recently introduced Granite-Docling-258M, a new open-source vision-language model (VLM) designed for high-fidelity document-to-text conversion while preserving complex layouts, tables, equations, and lists.

By Robert Krzaczyński

11 Sessions Not to Miss at QCon San Francisco 2025

As QCon San Francisco (Nov 17-21, 2025) approaches, the conference's program committee and track hosts are sharing their top picks from this year's lineup. Their selections span a wide range of topics, from AI-accelerated development and platform engineering to resilience patterns and career growth, all with QCon's signature focus on real-world case studies and lessons learned.

By Artenisa Chatziou


IBM in OEM Partnership with Cockroach Labs

NEW YORK, Oct. 7, 2025 — Cockroach Labs, the company behind the distributed SQL database CockroachDB, today announced an OEM partnership with IBM to bring CockroachDB PostgreSQL for IBM to market. This collaboration gives enterprises a trusted path to modernize mission-critical applications with a cloud-native PostgreSQL database engineered for active-active business continuity across hybrid environments—including IBM LinuxONE, Linux […]

What the OpenAI Deal Means for AMD in AI Factory Compute

Earlier this year, when the Stargate announcement at the White House kicked off a wave of eye-popping, hundreds-of-billion dollar data center investments, we might have been justified in assuming that it would be the tech story of the year. Then just a few weeks ago, NVIDIA stunned the technology world by investing $10 billion in […]


Colombian President Petro Says 'Hints Show' Latest Vessel Struck By The U.S. 'Was Colombian': 'It's a War For Oil'

Colombian President Gustavo Petro said there are "hints" that the latest vessel struck by the U.S. "was Colombian and had Colombian citizens" on it.

Republican Sen. Rand Paul Set To Cosponsor Initiative To Prevent Trump Admin From Striking Boats In The Caribbean

Republican Sen. Rand Paul said he will join Democratic colleagues in sponsoring a bill seeking to prevent the Trump administration from conducting strikes on suspected drug boats in the Caribbean

House Speaker Mike Johnson Pushes Back Against Marjorie Taylor Greene In Escalating Feud Over Health Care

House Speaker Mike Johnson pushed back against Rep. Marjorie Taylor Greene over her criticism of the party's plans for health care during the government shutdown

Z Group Architecture & Interior Design Is Shaping Luxury Living Through Designs That Connect People, Place, and Purpose

Z Group Architecture & Interior Design is a Colorado-based firm with deep roots and a modern approach to creating custom homes.

How Fascinations Has Been Leading the Mission of Destigmatizing Pleasure

With bright, open spaces, the company has crafted boutiques across Arizona and Colorado with an ambiance that aimed to signal approachability and care, setting a tone of self-expression and empowerment for visitors.

'Daily Struggle For Survival' For Haiti Children, UN Report Says

Fifteen-year-old Ania was raped by several men as she was fetching water, one of hundreds of thousands of young victims of gang violence that has engulfed Haiti and turned children's lives into a "daily struggle for survival," UNICEF warned in a report Wednesday.

From Health Care Executive to Managing Attorney: Building A Law Practice by Business Operators for Business Operators

Matthew T. Macklin's professional story is one of strategic innovation. Today, he serves as Managing Attorney of Stratagem Law Group, where he leads a firm dedicated to balancing legal rigor with pragmatic business insight.

Market Close Stock Round-Up October 8, 2025: S&P 500, NASDAQ And DOW Performances

Another day, another dollar; International Business Times' daily market close round-up is here.

Outgoing French PM Sees New Premier Named In Next 48 Hours

Outgoing French Prime Minister Sebastien Lecornu, who intensified a political crisis by resigning earlier this week, said Wednesday he expected President Emmanuel Macron to name a new premier within the next 48 hours.

US Facing Worsening Flight Delays As Shutdown Snarls Airports

Concerns over flight delays and missed paychecks due to the US government shutdown escalated Wednesday, as senators rejected yet another bid to end the standoff.

Jane Goodall's Final Wish: Blast Trump, Musk And Putin To Space

It's like the opposite of naming your dream dinner party guests. The conversation then turned to aggression in chimpanzees and whether the men she'd named were "alphas."

Man Arrested Over Deadly January Fire In Los Angeles

Authorities investigating one of the deadly fires that tore through Los Angeles in January said Wednesday they had arrested a man they believe deliberately started the blaze.

Tennis Stars Suffer, Wilt And Quit In 'Brutal' China Heat

Novak Djokovic threw up, Alexander Zverev poured sweat out of his shoe and Emma Raducanu quit her match with dizziness -- and the bad news for the world's top tennis players is that more baking weather is to come in China this week.

France's Le Pen Vows To Block Any Government

France's far-right leader Marine Le Pen said Wednesday she would thwart all action by any new government, throwing into doubt Prime Minister Sebastien Lecornu's ability to solve the country's deepening political crisis with a coalition cabinet.

Marjorie Taylor Greene Again Distances Herself From Trump: 'I'm Not Some Sort Of Blind Slave To The President'

Republican Rep. Marjorie Taylor Greene again distanced herself from parts of the Republican party and President Donald Trump, making it clear she will break with them when she considers it correct

Iran Releases Franco-German Accused Of Spying

Iran has released a 19-year-old Franco-German national days after throwing out spying charges against him, France's foreign minister told AFP on Wednesday.

Veggie 'Burgers' Face The Chop As EU Lawmakers Back Labeling Ban

Plant-based "steaks" and "veggie burgers" may be on the way out in the European Union after the bloc's parliament voted Wednesday to restrict such labels to meat only, in a win for disgruntled farmers.

World Economy Not Doing As Badly As Feared, IMF Chief Says

The global economy is doing better than expected, even as it faces prolonged uncertainty and underwhelming medium-term growth prospects, the head of the IMF said Wednesday.

Former FBI Chief James Comey Pleads Not Guilty In Case Pushed By Trump

Former FBI director James Comey pleaded not guilty on Wednesday to felony charges in a case widely seen as an escalation of President Donald Trump's campaign of retribution against political opponents.

Germany Raises Growth Forecasts, But Warns Reforms Needed

Germany's economy will eke out meagre growth in 2025 before picking up speed next year, the government Wednesday said as it raised forecasts, but called for "decisive reforms" for a sustained recovery.

EU Wants Key Sectors To Use Made-in-Europe AI

The EU on Wednesday told European businesses in critical sectors to ramp up their uptake of artificial intelligence and pushed for the bloc to cut its dependence on foreign AI providers.

Plenary Authority Explained: Stephen Miller Sparks Debate Over Presidential Power

Stephen Miller's viral claim about 'plenary authority' raises questions on presidential limits. Learn what the phrase actually means.

Arthur Hayes Alleges Euro Will Crash and Start New Crypto Revolution

X's favorite crypto provocateur, Arthur Hayes, believes a fresh wave of global money printing is about to launch Bitcoin past $200,000 — and, frankly, he might not be far off.

Top Democrats Set To Force Senate Vote To Block Trump's Strikes On Vessels Off Venezuela's Coast

Democratic Senator Adam Schiff anticipated that he, along with colleague Tim Kaine, will force a vote to block the strikes on vessels off the Venezuelan coast, which the Trump administration claims is aimed at eradicating drug-trafficking

Canal Istanbul Stirs Fear And Uncertainty In Nearby Villages

In Sazlibosna village, along the planned route of the vast Canal Istanbul project, 68-year-old Yasar Demirkaya fidgets with worn prayer beads as he sips tea at a cafe, uncertain about the future.


A Complete Guide to Seaborn

Seaborn is a statistical visualization library for Python that sits on top of Matplotlib. It gives you clean defaults, tight integration with Pandas DataFrames, and high-level functions that reduce boilerplate.

10 Command-Line Tools Every Data Scientist Should Know

Get control of your data workflows with these essential CLI tools.


Ex-Google CEO tells UK founders: ‘Please don’t sell for $100m’

无摘要

Octopus CEO says Reform UK 'has a point' on energy bills

无摘要

Gaming the chatbots: how startups are chasing AI search mentions

无摘要

How to get started with AI search

无摘要


These simple Bose headphones might be better than the QuietComfort Ultra - especially at this price

Exceptional noise cancellation and all-day comfort at $160 off is a solid deal.

Here's your last chance on the 30 best Prime Day Best Buy deals

October Prime Day may be in full swing, but Best Buy is running its own sale with major discounts on everything from laptops to TVs later this month.

Best Amazon Prime Day TV deals: Last chance to save up to $1,600 on LG, Samsung, and more

It's day two of Amazon's Prime Big Deal Days sale, and we're seeing some all-time low prices on TVs from Samsung, Hisense, Sony, and more.

We grabbed the 100+ best deals for Prime Day 2: Last chance on discounts up to 56% off on TVs, Kindles, & more

The final hours of October Prime Day are upon us, and we've seen some of the lowest prices ever on laptops, TVs, Apple products, and more.

Best Amazon Prime Day phone deals in October 2025: Last chance savings on Google, Samsung, more

October is the best time to buy a phone. These deals make it even better - but they'll be gone in a few hours.

Last chance to shop Prime Day Kindle deals on Paperwhite, Scribe, and more

Looking to cross more books off your reading list? Shop deals on Kindles right now and cross more books off your to-read list during the final hours of Prime Day.

Last chance to grab up to 50% off on the 21 best Prime Day tablet deals

October Prime Day is nearly over. We found the best tablet deals still going strong from top brands on the last day of the Prime Day.

Best Costco deals to compete with Amazon Prime Day 2025: Sales from Apple, LG, and more

Amazon Prime Day is winding down, but don't miss these deals that are still running on Costco right now.

The countdown is on: I found the best Amazon Prime Day Echo device deals expiring tonight

October Prime Day is underway, and Amazon Echo devices are available at great deals for the next few hours.

Best Amazon Prime Day Anker deals in October 2025: Save up to $400

Prime Day is here, and I've found some of the best deals on top-quality Anker power banks and chargers.

Here's the lowest-priced Chromebook I found on Prime Day - why I recommend it

Lenovo's IdeaPad Slim 3 Chromebook (2024) is on sale for $176 and comes with a MicroSD card slot for easy storage.

Best Amazon Prime Day EcoFlow deals in October 2025: I found discounts up to 51% off

Amazon Prime Day is winding down, but we've found some of the best deals on top-quality portable power stations from EcoFlow. Your time to save thousand of dollars!

Skip Amazon: We gathered the best Sam's Club deals competing with Prime Day 2025

You don't have to run to Amazon to find great deals for October Prime Day. Competitors like Sam's Club are also offering discounts on top tech products during Prime Day.

Best Target Circle Week deals to compete with October Prime Day 2025

Target is running a shopping event to compete with Amazon's October Prime Day. Here are the best tech deals I've found.

Best Walmart deals to compete with Prime Day: My favorite deals from Apple, Samsung, and HP

Amazon Prime Day is almost over, but you can still find great tech at Walmart for a lot less. Here are my favorite deals, including laptops, smartwatches, TVs, and smart home gadgets.

Here's your last chance on the 30 best Prime Day deals under $100

Pinching pennies? Pick up excellent (and affordable) tech during the final hours of Amazon's Prime Big Deal Days.

I test robot vacuums for work and my favorite one ever is $300 off - for a few more hours

The Deebot X11 OmniCyclone outperforms all the robot vacuums I've tested, and this Prime Day deal makes it even more appealing.

I tested Google's $130 Pixel Buds for a week, and they made pricier models feel unworthy

Google's Pixel Buds 2a deliver significant upgrades for a pair of midrange earbuds, but how close are they to their more expensive siblings?

Samsung Galaxy Z Fold 7 vs. Google Pixel 10 Pro Fold: We tested both, there's a clear winner

Samsung and Google's new foldables target different types of users - here's how to decide which one to buy.

Best Amazon Prime Day smartwatch deals in October 2025: Don't miss out on deals from Apple, Google, and Samsung

During the finals hours of Prime Day, I've rounded up the smartwatch and health tracker deals I'd shop during Amazon's deal event.


These simple Bose headphones might be better than the QuietComfort Ultra - especially at this price

Exceptional noise cancellation and all-day comfort at $160 off is a solid deal.

Here's your last chance on the 30 best Prime Day Best Buy deals

October Prime Day may be in full swing, but Best Buy is running its own sale with major discounts on everything from laptops to TVs later this month.

Best Amazon Prime Day TV deals: Last chance to save up to $1,600 on LG, Samsung, and more

It's day two of Amazon's Prime Big Deal Days sale, and we're seeing some all-time low prices on TVs from Samsung, Hisense, Sony, and more.

We grabbed the 100+ best deals for Prime Day 2: Last chance on discounts up to 56% off on TVs, Kindles, & more

The final hours of October Prime Day are upon us, and we've seen some of the lowest prices ever on laptops, TVs, Apple products, and more.

Best Amazon Prime Day phone deals in October 2025: Last chance savings on Google, Samsung, more

October is the best time to buy a phone. These deals make it even better - but they'll be gone in a few hours.

Last chance to shop Prime Day Kindle deals on Paperwhite, Scribe, and more

Looking to cross more books off your reading list? Shop deals on Kindles right now and cross more books off your to-read list during the final hours of Prime Day.

Last chance to grab up to 50% off on the 21 best Prime Day tablet deals

October Prime Day is nearly over. We found the best tablet deals still going strong from top brands on the last day of the Prime Day.

Best Costco deals to compete with Amazon Prime Day 2025: Sales from Apple, LG, and more

Amazon Prime Day is winding down, but don't miss these deals that are still running on Costco right now.

The countdown is on: I found the best Amazon Prime Day Echo device deals expiring tonight

October Prime Day is underway, and Amazon Echo devices are available at great deals for the next few hours.

Best Amazon Prime Day Anker deals in October 2025: Save up to $400

Prime Day is here, and I've found some of the best deals on top-quality Anker power banks and chargers.

Here's the lowest-priced Chromebook I found on Prime Day - why I recommend it

Lenovo's IdeaPad Slim 3 Chromebook (2024) is on sale for $176 and comes with a MicroSD card slot for easy storage.

Best Amazon Prime Day EcoFlow deals in October 2025: I found discounts up to 51% off

Amazon Prime Day is winding down, but we've found some of the best deals on top-quality portable power stations from EcoFlow. Your time to save thousand of dollars!

Skip Amazon: We gathered the best Sam's Club deals competing with Prime Day 2025

You don't have to run to Amazon to find great deals for October Prime Day. Competitors like Sam's Club are also offering discounts on top tech products during Prime Day.

Best Target Circle Week deals to compete with October Prime Day 2025

Target is running a shopping event to compete with Amazon's October Prime Day. Here are the best tech deals I've found.

Best Walmart deals to compete with Prime Day: My favorite deals from Apple, Samsung, and HP

Amazon Prime Day is almost over, but you can still find great tech at Walmart for a lot less. Here are my favorite deals, including laptops, smartwatches, TVs, and smart home gadgets.

Here's your last chance on the 30 best Prime Day deals under $100

Pinching pennies? Pick up excellent (and affordable) tech during the final hours of Amazon's Prime Big Deal Days.

I test robot vacuums for work and my favorite one ever is $300 off - for a few more hours

The Deebot X11 OmniCyclone outperforms all the robot vacuums I've tested, and this Prime Day deal makes it even more appealing.

I tested Google's $130 Pixel Buds for a week, and they made pricier models feel unworthy

Google's Pixel Buds 2a deliver significant upgrades for a pair of midrange earbuds, but how close are they to their more expensive siblings?

Samsung Galaxy Z Fold 7 vs. Google Pixel 10 Pro Fold: We tested both, there's a clear winner

Samsung and Google's new foldables target different types of users - here's how to decide which one to buy.

Best Amazon Prime Day smartwatch deals in October 2025: Don't miss out on deals from Apple, Google, and Samsung

During the finals hours of Prime Day, I've rounded up the smartwatch and health tracker deals I'd shop during Amazon's deal event.


Anthropic AI Releases Petri: An Open-Source Framework for Automated Auditing by Using AI Agents to Test the Behaviors of Target Models on Diverse Scenarios

How do you audit frontier LLMs for misaligned behavior in realistic multi-turn, tool-use settings—at scale and beyond coarse aggregate scores? Anthropic released Petri (Parallel Exploration Tool for Risky Interactions), an open-source framework that automates alignment audits by orchestrating an auditor agent to probe a target model across multi-turn, tool-augmented interactions and a judge model to […]

The post Anthropic AI Releases Petri: An Open-Source Framework for Automated Auditing by Using AI Agents to Test the Behaviors of Target Models on Diverse Scenarios appeared first on MarkTechPost.

Model Context Protocol (MCP) vs Function Calling vs OpenAPI Tools — When to Use Each?

Comparison Table Concern MCP Function Calling OpenAPI Tools Interface contract Protocol data model (tools/resources/prompts) Per-function JSON Schema OAS 3.1 document Discovery Dynamic via tools/list Static list provided to the model From OAS; catalogable Invocation tools/call over JSON-RPC session Model selects function; app executes HTTP request per OAS op Orchestration Host routes across many servers/tools App-local […]

The post Model Context Protocol (MCP) vs Function Calling vs OpenAPI Tools — When to Use Each? appeared first on MarkTechPost.

Google AI Introduces Gemini 2.5 ‘Computer Use’ (Preview): A Browser-Control Model to Power AI Agents to Interact with User Interfaces

Which of your browser workflows would you delegate today if an agent could plan and execute predefined UI actions? Google AI introduces Gemini 2.5 Computer Use, a specialized variant of Gemini 2.5 that plans and executes real UI actions in a live browser via a constrained action API. It’s available in public preview through Google […]

The post Google AI Introduces Gemini 2.5 ‘Computer Use’ (Preview): A Browser-Control Model to Power AI Agents to Interact with User Interfaces appeared first on MarkTechPost.

Meta AI Open-Sources OpenZL: A Format-Aware Compression Framework with a Universal Decoder

How much compression ratio and throughput would you recover by training a format-aware graph compressor and shipping only a self-describing graph to a universal decoder? Meta AI released OpenZL, an open-source framework that builds specialized, format-aware compressors from high-level data descriptions and emits a self-describing wire format that a universal decoder can read—decoupling compressor evolution […]

The post Meta AI Open-Sources OpenZL: A Format-Aware Compression Framework with a Universal Decoder appeared first on MarkTechPost.


Using generative AI to diversify virtual training grounds for robots

New tool from MIT CSAIL creates realistic virtual kitchens and living rooms where simulated robots can interact with models of real-world objects, scaling up training data for robot foundation models.

Uncovering new physics in metals manufacturing

MIT researchers discovered a hidden atomic order that persists in metals even after extreme processing.


The Download: carbon removal factories’ funding cuts, and AI toys

This is today’s edition of The Download, our weekday newsletter that provides a daily dose of what’s going on in the world of technology. The Trump administration may cut funding for two major direct-air capture plants The US Department of Energy appears poised to terminate funding for a pair of large carbon-sucking factories that were originally set…


Memory chips just 10 atoms thick could vastly increase capacity

A memory chip just 10 atoms thick has been tested in a lab and integrated into conventional chips, demonstrating a technology that could improve the capacity of our devices


People-pleasing chatbots may boost your ego, but they can weaken your judgment

Most people enjoy receiving praise occasionally, but if it comes from sycophantic chatbots, it could be doing you more harm than good. Computer scientists from Stanford University and Carnegie Mellon University have found that people-pleasing chatbots can have a detrimental impact on our judgment and behavior.

What AI-generated Tilly Norwood reveals about digital culture, ethics and the responsibilities of creators

Imagine an actor who never ages, never walks off set or demands a higher salary.

Novel AI tool opens 3D modeling to blind and low-vision programmers

Blind and low-vision programmers have long been locked out of three-dimensional modeling software, which depends on sighted users dragging, rotating and inspecting shapes on screen.

EU wants key sectors to use made-in-Europe AI

The EU on Wednesday told European businesses in critical sectors to ramp up their uptake of artificial intelligence and pushed for the bloc to cut its dependence on foreign AI providers.

AI tools promise efficiency at work, but they can erode trust, creativity and agency

What if your biggest competitive asset is not how fast AI helps you work, but how well you question what it produces?

Would you watch a film with an AI actor? What Tilly Norwood tells us about art—and labor rights

Tilly Norwood officially launched her acting career this month at the Zurich Film Festival.

Today's AI hype has echoes of a devastating technology boom and bust 100 years ago

The electrification boom of the 1920s set the United States up for a century of industrial dominance and powered a global economic revolution.

Chatbot dreams generate AI nightmares for Bay Area lawyers

A Palo Alto, California, lawyer with nearly a half-century of experience admitted to an Oakland federal judge this summer that legal cases he referenced in an important court filing didn't actually exist and appeared to be products of artificial intelligence "hallucinations."

Cyber defense innovation could significantly boost 5G network security

A framework for building tighter security into 5G wireless communications has been created by a Ph.D. student working with the University of Portsmouth's Artificial Intelligence and Data Center.

Anthropic to open India office as AI demand grows

US startup Anthropic on Wednesday said it plans to open an office in India next year, as global generative AI players seek inroads into the world's most populous country.

SoftBank buys $5.4 bn robotics firm to advance 'physical AI'

Tech investment giant SoftBank Group said Wednesday it will buy Swiss-Swedish firm ABB Robotics for nearly $5.4 billion as part of its plans to bring artificial intelligence into the physical realm.


People-pleasing chatbots may boost your ego, but they can weaken your judgment

Most people enjoy receiving praise occasionally, but if it comes from sycophantic chatbots, it could be doing you more harm than good. Computer scientists from Stanford University and Carnegie Mellon University have found that people-pleasing chatbots can have a detrimental impact on our judgment and behavior.

What AI-generated Tilly Norwood reveals about digital culture, ethics and the responsibilities of creators

Imagine an actor who never ages, never walks off set or demands a higher salary.

Novel AI tool opens 3D modeling to blind and low-vision programmers

Blind and low-vision programmers have long been locked out of three-dimensional modeling software, which depends on sighted users dragging, rotating and inspecting shapes on screen.

EU wants key sectors to use made-in-Europe AI

The EU on Wednesday told European businesses in critical sectors to ramp up their uptake of artificial intelligence and pushed for the bloc to cut its dependence on foreign AI providers.

AI tools promise efficiency at work, but they can erode trust, creativity and agency

What if your biggest competitive asset is not how fast AI helps you work, but how well you question what it produces?

Would you watch a film with an AI actor? What Tilly Norwood tells us about art—and labor rights

Tilly Norwood officially launched her acting career this month at the Zurich Film Festival.

Today's AI hype has echoes of a devastating technology boom and bust 100 years ago

The electrification boom of the 1920s set the United States up for a century of industrial dominance and powered a global economic revolution.

Chatbot dreams generate AI nightmares for Bay Area lawyers

A Palo Alto, California, lawyer with nearly a half-century of experience admitted to an Oakland federal judge this summer that legal cases he referenced in an important court filing didn't actually exist and appeared to be products of artificial intelligence "hallucinations."

Cyber defense innovation could significantly boost 5G network security

A framework for building tighter security into 5G wireless communications has been created by a Ph.D. student working with the University of Portsmouth's Artificial Intelligence and Data Center.

Anthropic to open India office as AI demand grows

US startup Anthropic on Wednesday said it plans to open an office in India next year, as global generative AI players seek inroads into the world's most populous country.

SoftBank buys $5.4 bn robotics firm to advance 'physical AI'

Tech investment giant SoftBank Group said Wednesday it will buy Swiss-Swedish firm ABB Robotics for nearly $5.4 billion as part of its plans to bring artificial intelligence into the physical realm.


Training Federated AI Models to Predict Protein Properties

Predicting where proteins are located inside a cell is critical in biology and drug discovery. This process is known as subcellular localization. The location...


His Lab Tested Cutting-Edge Spacecraft

Mason Peck, an aerospace engineer at Cornell, was trying to test innovative designs in spacecraft when a stop-work order hit.

Has Your Scientific Work Been Cut? We Want to Hear.

For a new series, Times journalists are speaking with scientists whose research has ended as a result of policy changes by the Trump administration.

A.I. Companion Ads for Friend.com Flood NYC Subway, Fueling Backlash and Vandalism

An ad campaign for a wearable A.I. companion has blanketed New York City, starting conversations and inspiring vandalism.


Did You Know That There Are Camera-Less iPhones?

A close-up of a black iPhone placed on a white surface, showing the Apple logo and part of the word "iPhone" on the back.

For most iPhone owners, the smartphone's cameras are a massive draw. However, as a recent post on Reddit shows, for those who work in sensitive industries, their iPhone may not even have a camera at all. There's an entire specialized industry focused on stripping the camera systems from Apple's handhelds.

[Read More]

The Flashback ONE35 V2 Lets You Shoot Instantly, But You Still Get the Film Experience

Nine retro-style cameras in various colors and designs are arranged in a grid pattern on a gray surface. Each camera has a unique combination of color accents and the label “Flashback” near the lens.

Flashback, the company that makes "non-disposable digital disposable cameras", has today released its second model called the ONE35 V2.

[Read More]

How Fujifilm Changed the GFX Eterna 55’s 100MP Sensor for Filmmaking

A compact, black professional camera body with exposed sensor, various control dials, and a large side grip, displayed against an orange gradient background.

At first glance, the 101-megapixel medium-format image sensor in Fujifilm's brand-new GFX Eterna 55 cinema camera looks very much like the sensor featured in the GFX100 II and GFX100S II. However, as Fujifilm details in its latest "GFX Eterna 55 Development Story," the truth is much more complicated than that.

[Read More]

Historian Finally Identifies Nazi in Infamous Holocaust Photo Using AI

A group of uniformed soldiers stand outdoors as one soldier points a gun at a kneeling man with glasses, suggesting an execution scene; other men observe somberly in the background. The image is in black and white.

One of the most horrifying photographs depicting the Holocaust taking place in an occupied part of the Soviet Union during World War II has been properly identified thanks to years of research and the help of artificial intelligence.

[Read More]

How an AP Photographer Told a Sleepy Scientist She Won the Nobel Prize

A dimly lit home scene split in two: on the left, a man and a woman greet a dog at the door; on the right, the woman sits at a table, looking down with her head in her hand beside an open laptop.

Scientists Mary E. Brunkow, Fred Ramsdell, and Dr. Shimon Sakaguchi won the Nobel Prize in medicine this week. Associated Press photographer Lindsey Wasson was the one who delivered the incredible news to Brunkow at her Seattle-area home in the very early hours on Monday morning.

[Read More]

LightPix Labs’ New Flash Looks Like the Perfect Match for Retro-Inspired Mirrorless Cameras

A silver Contax film camera with a lens is placed on a flat surface. A Flash FM2 unit sits on top, and a small LightPix Labs camera accessory is positioned to the right. The background is plain and gray.

LightPix Labs has announced the FlashQ FM2, a retro-inspired, sleek, and compact wireless flash system designed for photographers who appreciate both style and substance.

[Read More]

Robin Williams’ Daughter Condemns Sora 2 AI Videos of Her Late Father

A woman and a man stand close together, both with surprised and animated facial expressions. The background features a movie poster with cars and bright colors.

Zelda Williams, daughter of the late actor and comedian Robin Williams, has condemned the use of artificial intelligence to create digital recreations of her father.

[Read More]

Despite Reports to the Contrary, Nikon Says It Has Not Discontinued Its First Nikkor Z Lens

A black camera zoom lens with multiple control rings and a digital display, marked “24-70mm f/2.8 S,” is displayed on a bright yellow background.

Last week, reports surfaced that the original Nikon Nikkor Z 24-70mm f/2.8 S, which has just been succeeded by the excellent new Nikkor Z 24-70mm f/2.8 S II, had been discontinued. Nikon says this is not true.

[Read More]

Photo Management App Peakto Now Has Secure Online Collaboration

A lively, lantern-lit street in Japan at night with people walking. Overlayed is a chat window titled "Sharespace," showing a conversation about photo compositions and nighttime photos. The number "2.5" appears at the bottom.

Photography software developer Cyme has announced Peakto 2.5, the latest version of its AI-powered media management app for macOS. Peakto 2.5 turns the user's Mac into a secure server, enabling photographers to share their content for collaboration online via an encrypted network connection.

[Read More]

This is What a Starlink Satellite Train Looks Like from the ISS

A view of the Orion constellation shining brightly above Earth, with the green and purple hues of an aurora and Earth's thin blue atmosphere visible below.

Astronaut Don Pettit splashed back down to Earth in April, and he is still "throttling down" from his six-month voyage on board the International Space Station -- and that includes sifting through the troves of videos and photos he captured while in orbit.

[Read More]


Loops of DNA Equipped Ancient Life To Become Complex

New work shows that physical folding of the genome to control genes located far away may have been an early evolutionary development.

The post Loops of DNA Equipped Ancient Life To Become Complex first appeared on Quanta Magazine


The Chinese migrant workers powering the deadly EV nickel boom

traffic around one of the main crossings near an entrance of the industrial compound in Morowali


SoftBank bets on “Physical AI” with $5.4B acquisition of ABB’s robotics division

Swedish-Swiss company ABB today announced it has signed an agreement to divest its Robotics division to SoftBank Group for an enterprise value of $5.375 billion and not pursue its earlier intention to...

Cyberwave raises €7M to make the physical world programmable

Milan’s Cyberwave, which builds anoperating layer between AI agents and real-world machines, has raised €7million in a round led by United Ventures with participation from The TechShop,alongside seed ...


Will AI Ever Win a Nobel Prize?

Some researchers think artificial intelligence could produce Nobel-worthy research, but others question whether autonomous AI scientists are possible or even desirable

After 30 Years of Discovery, These Are Astronomers’ Top Five Exoplanets

Space scientists look back on three decades of exoplanet discoveries—from rows of massive ‘super-Earths‘ to worlds with perfectly synchronized orbits

Why Scammers Target Seniors—And What You Can Do About It

Millions of older adults lose their savings to scams every year. There are ways to reduce the risk

2025 Chemistry Nobel Goes to Molecular Sponges That Purify Water, Store Energy and Clean Up the Environment

Three scientists, including one from the U.S., share the 2025 Nobel Prize in Chemistry for developing “metal-organic frameworks,” versatile molecular cages that can trap contaminants, store energy and possibly deliver drugs to specific areas of the body

AI Scans Tongue Color to Predict Diseases

Inspired by principles from traditional Chinese medicine, researchers used AI to analyze tongue color as a diagnostic tool—with more than 96 percent accuracy

Astronaut Chris Hadfield Explores Cold War Geopolitics in New Novel

Astronaut-turned-author Chris Hadfield discusses his new thriller Final Orbit, which weaves real cold war history, space race geopolitics and firsthand experience into a gripping work of fiction.


Galway’s Fortis Medical gets €2.1m DTIF award for post-stroke wearable

Issues with walking are common after stroke, and healthcare providers need more data to help.

Read more: Galway’s Fortis Medical gets €2.1m DTIF award for post-stroke wearable

Skillnet Ireland to receive €54.2m from Budget 2026

The funding will be used as part of a wider strategy to leverage upskilling and meet the needs of the changing entrepreneurial landscape.

Read more: Skillnet Ireland to receive €54.2m from Budget 2026

Top tips for improving organisational cyber hygiene

A company is only as strong as its cybersecurity network so employees and employers are equally as responsible in ensuring a safe and productive environment.

Read more: Top tips for improving organisational cyber hygiene

Nobel Prize in Chemistry awarded for porous molecular innovation

The trio’s work on developing metal-organic frameworks can be used to harvest water from desert air, capture carbon dioxide or catalyse chemical reaction.

Read more: Nobel Prize in Chemistry awarded for porous molecular innovation

How to stay ahead of NIS2 and the latest EU cybersecurity rules

Legal expert Ricky Kelly from RDJ explains the current cyber regulatory landscape and what businesses can do to stay up to date.

Read more: How to stay ahead of NIS2 and the latest EU cybersecurity rules

Linux Foundation to set up open-source governance body for React

The React Foundation will maintain React's infrastructure, organise events and creative initiatives to support the React ecosystem.

Read more: Linux Foundation to set up open-source governance body for React

SoftBank to acquire ABB robotics unit in multibillion-dollar deal

The deal is expected to be finalised in mid to late 2026, subject to regulatory approvals and closing conditions.

Read more: SoftBank to acquire ABB robotics unit in multibillion-dollar deal


Python 3.14 Is Here. How Fast Is It?

Python 3.14 Is Here. How Fast Is It?

Miguel Grinberg uses some basic benchmarks (like fib(40)) to test the new Python 3.14 on Linux and macOS and finds some substantial speedups over Python 3.13 - around 27% faster.

The optional JIT didn't make a meaningful difference to his benchmarks. On a threaded benchmark he got 3.09x speedup with 4 threads using the free threading build - for Python 3.13 the free threading build only provided a 2.2x improvement.

Via lobste.rs

Tags: gil, performance, python

### [Quoting Simon Højberg](https://simonwillison.net/2025/Oct/8/simon-hojberg/#atom-everything)

The cognitive debt of LLM-laden coding extends beyond disengagement of our craft. We’ve all heard the stories. Hyped up, vibed up, slop-jockeys with attention spans shorter than the framework-hopping JavaScript devs of the early 2010s, sling their sludge in pull requests and design docs, discouraging collaboration and disrupting teams. Code reviewing coworkers are rapidly losing their minds as they come to the crushing realization that they are now the first layer of quality control instead of one of the last. Asked to review; forced to pick apart. Calling out freshly added functions that are never called, hallucinated library additions, and obvious runtime or compilation errors. All while the author—who clearly only skimmed their “own” code—is taking no responsibility, going “whoopsie, Claude wrote that. Silly AI, ha-ha.”

Simon Højberg, The Programmer Identity Crisis

Tags: llms, generative-ai, ai, code-review, ai-ethics

### [Why NetNewsWire Is Not a Web App](https://simonwillison.net/2025/Oct/8/why-netnewswire-is-not-a-web-app/#atom-everything)

Why NetNewsWire Is Not a Web App

In the wake of Apple removing ICEBlock from the App Store, Brent Simmons talks about why he still thinks his veteran (and actively maintained) NetNewsWire feed reader app should remain a native application.

Part of the reason is cost - NetNewsWire is free these days (MIT licensed in fact) and the cost to Brent is an annual Apple developer subscription:

If it were a web app instead, I could drop the developer membership, but I’d have to pay way more money for web and database hosting. [...] I could charge for NetNewsWire, but that would go against my political goal of making sure there’s a good and free RSS reader available to everyone.

A bigger reason is around privacy and protecting users:

Second issue. Right now, if law enforcement comes to me and demands I turn over a given user’s subscriptions list, I can’t. Literally can’t. I don’t have an encrypted version, even — I have nothing at all. The list lives on their machine (iOS or macOS).

And finally it's about the principle of what a personal computing device should mean:

My computer is not a terminal. It’s a world I get to control, and I can use — and, especially, make — whatever I want. I’m not stuck using just what’s provided to me on some other machines elsewhere: I’m not dialing into a mainframe or doing the modern equivalent of using only websites that other people control.

<p>Tags: <a href="https://simonwillison.net/tags/apple">apple</a>, <a href="https://simonwillison.net/tags/brent-simmons">brent-simmons</a>, <a href="https://simonwillison.net/tags/macos">macos</a>, <a href="https://simonwillison.net/tags/netnewswire">netnewswire</a>, <a href="https://simonwillison.net/tags/ios">ios</a></p>

A new look for comments

Learn about what’s new with comments on Stack Overflow


Build and Test Document-Based AI Agents with Synthetic Data

Editor’s note: Fabiana Clemente is a speaker for ODSC AI West this October 288th-30th in San Francisco. Check out her talk, Build and Test Document-Based AIAgents with Synthetic Data, there!

Your company has thousands of invoices sitting in PDFs. They contain information that you need to develop the AI system that you were asked to, but you hit a wall. The documents are under strict privacy restrictions, inconsistent formats and even missing data. So, what do you do?

The truth is, organizations run on documents. Invoices keep the money moving. Contracts govern relationships. Compliance records keep regulators satisfied. It is no overstatement to say that inside these files lies the most valuable data a business can own — the map of how organizations truly operate.

However, there is a catch. The very documents that are rich in insights are also often the most difficult to use. They’re scattered across silos, restricted by privacy regulations, and locked away in static formats like PDFs and PNGs. For AI system development, these are huge bottlenecks.

For effective AI Engineering, making documents both safe to use (privacy-preserving) and easy to parse (machine-readable) is key to unlocking the development of a new class of AI applications, such as contract summarization, anomaly spotting in financial records, or even processing thousands of invoices without human intervention. And since real-world data is often off-limits, we’ll start with the foundation, synthetic document generation.

Generate Synthetic Documents

To kickstart, we need to generate mock documents for our agent to handle. For that purpose, we will be leveraging ydata-sdk, which allows us to generate synthetic documents for invoices and bank transactions. The framework can generate documents in multiple formats, including PDFs, PNGs, and HTML. For the purpose of this example, we will be generating multiple PDFs.

Given that we want to mimic internal invoices, we have decided to generate invoices in the corporate context, related to the services provided.

Below is a code snippet with an example of how we will be generating the synthetic data during the workshop:

“””

Code example: Generating synthetic invoices with ydata-sdk

“””

from ydata.synthesizers.text.model.document import DocumentGenerator, DocumentFormat
generator = DocumentGenerator(document_format=DocumentFormat.PDF)
generator.generate(
n_docs=1, # Generate one document
document_type="Invoice", # Type of document to generate
audience="Corporate client", # Target audience
tone="professional", # Writing tone
purpose="Issue a detailed invoice for services rendered. Please provide detailed examples and real line items", # Document purpose
region="North America", # Regional context
language="English", # Output language
length="Long", # Document length (invoices are usually not long)
topics="Consulting services, Hourly rates, Tax breakdown, Payment terms",
# Key topics as a single comma-separated string
style_guide="Professional design for a financial institution", # Style or branding requirements
output_dir="output/documents", # Output directory
)

This small snippet produces a simple invoice (as shown in the images below). In real-world scenarios, you’d vary layout templates, inject noise or layout errors, and even sample distributions of line-items.

From Documents to Agents

Of course, generating PDFs is only the starting point. To turn them into something an AI agent can actually use, we need to transform static files into structured, searchable knowledge. This will be the heart of the workshop. Together, we’ll go through:

  • Parsing and chunking. Documents are first parsed and split into smaller pieces, allowing details such as invoice totals or transaction rows to be retrieved later.
  • Storing in a vector database. Each chunk is converted into an embedding and stored in a vector database. This enables semantic search — so the system can find relevant passages even if the question is phrased differently.
  • Retrieval-Augmented Generation (RAG). Finally, we connect the database to a large language model. When a question is asked, the agent retrieves the most relevant chunks and uses them as context to generate an accurate answer.

By the end of the workshop, you’ll have built a complete pipeline: from synthetic invoices and statements all the way to a working AI agent that can answer questions about them.

Conclusion

To have a proper document-processing pipeline in place it is more than just a technical exercise, it is rather a practical enabler for AI development. By combining synthetic document generation, structuring static formats like PDFs and PNGs, and applying Retrieval-Augmented Generation (RAG), it provides a clear path to building and testing document-driven AI agents.

Join my ODSC West talk to deep-dive into document preparation for AI development. You’ll be able to learn and implement the full pipeline of document processing for RAG and AI Agents development. Step by step, you’ll learn how to bring these pieces together and leave with a working foundation for developing your own document-driven solutions.

About the Author/ODSC AI West Speaker:

Fabiana Clemente is the co-founder and CDO of YData, combining Data Understanding, Causality, and Privacy as her main fields of work and research, with the mission to make data actionable for organizations. Passionate for data, Fabiana has vast experience leading data science teams in startups and multinational companies. Host of “When Machine Learning meets privacy” podcast and a guest speaker at Datacast and Privacy Please, the previous WebSummit speaker, was recently awarded “Founder of the Year” by the South Europe Startup Awards.


Even after Stargate, Oracle, Nvidia and AMD, OpenAI has more big deals coming soon, Sam Altman says

By some estimates, OpenAI has this year inked $1 trillion dollars worth of infrastructure deals. Altman says to expect even more.

Here’s what it’s really like to appear on billionaire VC Tim Draper’s ‘Meet the Drapers’ pitch show

The show is one of many on Draper's newly launched television channel, DraperTV, which offers programming around business and entrepreneurship, available via streaming services like Roku.

OpenAI’s Nick Turley on transforming ChatGPT into an operating system

In an interview, OpenAI's Head of ChatGPT discusses the company's push into developing an AI operating system full of third-party apps.

Sora’s downloads in its first week was nearly as big as ChatGPT’s launch

This level of consumer adoption is worth noting because Sora remains an invite-only app, while ChatGPT was more publicly available at launch. That makes Sora's performance more impressive.

Elon Musk will settle $128M lawsuit with former Twitter execs

The four executives never received severance payments, which they claim is because they tried to hold Musk to his $44 billion commitment when he tried to back out of buying the company.

Amazon Pharmacy is launching vending machines for prescription drugs

The kiosks have a range of commonly prescribed medications, including antibiotics, inhalers, and blood pressure medications.

Here’s the tech powering ICE’s deportation crackdown

From phone spyware and facial recognition to phone unlocking technology and databases and more, this tech powers Trump's deportation machine.

Zendesk says its new AI agent can solve 80% of support issues

Zendesk has launched a new autonomous support agent that should solve 80% of support issues without human intervention.

H-1B visa changes explained: The loophole costing startups talent

Today on TechCrunch’s ⁠Equity⁠ podcast, Dominic-Madori Davis was joined by ⁠Jeremy Neufeld⁠, the Director of Immigration Policy at the Institute for Progress, to break down what the recent H-1B change means for startups, founders, and the future of tech talent in America.  Watch the full episode for more about:  Equity is TechCrunch’s flagship podcast, produced […]

AST SpaceMobile lands key Verizon deal amid growing competition with SpaceX and T-Mobile

AST SpaceMobile is deepening its relationship with mobile carrier giant Verizon.

Base Power raises $1B to deploy home batteries everywhere

Base Power's Series C will help the company expand beyond Texas, its beachhead market, and build batteries in the United States.

Bounce introduces a tool to move your Mastodon account to Bluesky

The idea is that this account portability prevents users from getting stuck on a service if they come to disagree with its state of development, terms of use, moderation decisions, or anything else.

Ganiga will showcase its waste-sorting robots at TechCrunch Disrupt 2025

Ganiga's fleet of waste-sorting technology is meant to help companies track and reduce the waste they produce.

A breakdown of the H-1B changes — and why more changes could come

Jeremy Neufeld, the director of immigration policy at the Institute for Progress, comes on Equity to talk H-1B changes.

Google’s virtual try-on shopping tool expands to more countries, now lets you try on shoes

To virtually try on a pair of shoes, users need to tap on any product listing on Google, select the "try it on" button, and add a full length photo themselves.

Unveiling the next wave of Startup Battlefield 200 VC judges at TechCrunch Disrupt 2025

Five more VC leaders from Accel, SevenSevenSix, Lockstep, IVP, and more join the Startup Battlefield 200 judge panel at TechCrunch Disrupt 2025. Register now to join this intense startup pitch competition live, and to save up to $444.

SoftBank bulks up its robotics portfolio with ABB Group’s robotics unit

SoftBank says this acquisition will help it dive deeper into robotics as it considers physical AI to be the next frontier.

From courtside to code: Tristan Thompson on AI, sports, and startups at TechCrunch Disrupt 2025

NBA champion Tristan Thompson joins TechCrunch Disrupt 2025 to discuss how AI and athletes are transforming sports, startups, and innovation. Register here to save up to $444 on your pass, or save up to 30% on group tickets.

Google launches extensions system for its command-line coding tool

Google launched a new feature for its command-line AI system, Gemini CLI, allowing outside companies to integrate directly into the product.

Square launches AI voice ordering and an integrated Bitcoin solution for merchants

Block is now allowing Square merchants to accept Bitcoin payments without any processing fee for one year


Verizon signs a commercial agreement with AST SpaceMobile to offer satellite-to-phone connectivity in cellular dead zones starting in 2026; ASTS closes up 8.6% (Michael Kan/PCMag)

Michael Kan / PCMag:
Verizon signs a commercial agreement with AST SpaceMobile to offer satellite-to-phone connectivity in cellular dead zones starting in 2026; ASTS closes up 8.6%  —  As SpaceX races to dominate satellite-to-phone services, Verizon is doubling down on rival AST SpaceMobile instead.

David AI, which sells audio data sets for AI training, raised a $50M Series B, sources say at a $500M valuation, up from ~$100M from its $25M Series A in May (Shirin Ghaffary/Bloomberg)

Shirin Ghaffary / Bloomberg:
David AI, which sells audio data sets for AI training, raised a $50M Series B, sources say at a $500M valuation, up from ~$100M from its $25M Series A in May  —  David AI Labs Inc. a startup selling audio data sets to help train artificial intelligence models, has raised $50 million …

Prosecutors say the evidence against a man accused of starting what became the Pacific Palisades fire includes a ChatGPT-generated image of a burning city (Los Angeles Times)

Los Angeles Times:
Prosecutors say the evidence against a man accused of starting what became the Pacific Palisades fire includes a ChatGPT-generated image of a burning city  —  - Authorities have arrested a suspect in the Palisades fire after a nine-month investigation into the blaze that killed 12 people.

New York City sues Meta, Alphabet, Snap, and ByteDance, accusing them of fueling a mental health crisis among children by addicting them to social media (Jonathan Stempel/Reuters)

Jonathan Stempel / Reuters:
New York City sues Meta, Alphabet, Snap, and ByteDance, accusing them of fueling a mental health crisis among children by addicting them to social media  —  - City alleges gross negligence, creating public nuisance  — ‘Subway surfing’ deaths attributed to social media  — Google denies accusations about YouTube

Relace, which makes tools and specialized language models to help AI agents code faster for customers like Lovable and Figma, raised a $23M Series A led by a16z (Stephanie Palazzolo/The Information)

Stephanie Palazzolo / The Information:
Relace, which makes tools and specialized language models to help AI agents code faster for customers like Lovable and Figma, raised a $23M Series A led by a16z  —  Countless startups sell tools to software engineers, such as version control systems to track who's making changes to a codebase …

Apple has removed Eyes Up, which archives video evidence of ICE abuses, from the App Store; unlike ICEBlock, it doesn't share ICE officers' real-time locations (Joseph Cox/404 Media)

Joseph Cox / 404 Media:
Apple has removed Eyes Up, which archives video evidence of ICE abuses, from the App Store; unlike ICEBlock, it doesn't share ICE officers' real-time locations  —  Apple removed an app for preserving TikToks, Instagram reels, news reports, and videos documenting abuses by ICE, 404 Media has learned.

Verizon agrees to buy Starry, which provides home internet via millimeter wave tech to ~100K customers and filed for bankruptcy in 2023, for an undisclosed sum (Masha Abarinova/Fierce Network)

Masha Abarinova / Fierce Network:
Verizon agrees to buy Starry, which provides home internet via millimeter wave tech to ~100K customers and filed for bankruptcy in 2023, for an undisclosed sum  —  Verizon Starry acquisition fixed wireless access  — Verizon is buying FWA provider Starry for an undisclosed sum

Sources: data streaming software maker Confluent is exploring a sale after attracting acquisition interest from PE firms and tech companies; CFLT jumps 9%+ (Milana Vinn/Reuters)

Milana Vinn / Reuters:
Sources: data streaming software maker Confluent is exploring a sale after attracting acquisition interest from PE firms and tech companies; CFLT jumps 9%+  —  - Firm working with bankers after attracting interest from private equity and tech firms, sources say

New York-based Crosby, a law firm that uses AI to help speed up the contracts process, raised a $20M Series A co-led by Index Ventures, BCV, and Elad Gil (Alex Konrad/Upstarts Media)

Alex Konrad / Upstarts Media:
New York-based Crosby, a law firm that uses AI to help speed up the contracts process, raised a $20M Series A co-led by Index Ventures, BCV, and Elad Gil  —  Crosby, led by lawyer turned founder Ryan Daniels, has raised a $20 million Series A from Index and Bain Capital Ventures to expand its AI-assisted legal work.

Google Pixel Buds 2a review: ANC is a welcome addition and sound is detailed and punchy, but there's still no wireless charging and voice performance suffers (Billy Steele/Engadget)

Billy Steele / Engadget:
Google Pixel Buds 2a review: ANC is a welcome addition and sound is detailed and punchy, but there's still no wireless charging and voice performance suffers  —  The Pixel Buds Pro 2 have more to offer, but there's plenty of performance here for less money.

Google Pixel Watch 4 review: a significant leap in Google's smartwatch lineup with a nice domed display, but Gemini is unreliable, and GPS maps are still wonky (Victoria Song/The Verge)

Victoria Song / The Verge:
Google Pixel Watch 4 review: a significant leap in Google's smartwatch lineup with a nice domed display, but Gemini is unreliable, and GPS maps are still wonky  —  Five years ago, I used to groan when it came time to review an Android smartwatch.  Back then, anything that wasn't a Samsung watch was disappointing at best.

Google Pixel 10 Pro Fold review: nice display and most AI features run on device, but cameras are a step down from other Pro Pixels, Tensor G5 shows small gains (Ryan Whitwam/Ars Technica)

Ryan Whitwam / Ars Technica:
Google Pixel 10 Pro Fold review: nice display and most AI features run on device, but cameras are a step down from other Pro Pixels, Tensor G5 shows small gains  —  Google delivers another phone that is slightly better than its predecessor—is that enough?  —  When the first foldable phones …

Chicago-based stablecoin payments startup Coinflow raised a $25M Series A led by Pantera and says it supports stablecoin-powered payments in 170+ countries (CoinDesk)

CoinDesk:
Chicago-based stablecoin payments startup Coinflow raised a $25M Series A led by Pantera and says it supports stablecoin-powered payments in 170+ countries  —  The company says it has grown revenue 23-fold since 2024 and now supports stablecoin-powered payments in over 170 countries.  —  What to know:

Germany's Federal Cartel Office opens an investigation into whether Temu is influencing the pricing of third-party merchants, potentially stifling competition (Mark Hallam/DW News)

Mark Hallam / DW News:
Germany's Federal Cartel Office opens an investigation into whether Temu is influencing the pricing of third-party merchants, potentially stifling competition  —  Germany's competition watchdog has announced an investigation of Chinese discount online retail site temu.com, suspecting it of influencing retailers' prices.

Filing: Elon Musk and X settle a lawsuit by former Twitter CEO Parag Agrawal, Chief Legal Officer Vijaya Gadde, and others over $128M+ in unpaid 2024 severance (Jess Weatherbed/The Verge)

Jess Weatherbed / The Verge:
Filing: Elon Musk and X settle a lawsuit by former Twitter CEO Parag Agrawal, Chief Legal Officer Vijaya Gadde, and others over $128M+ in unpaid 2024 severance  —  The settlement agreement over withheld severance is dependent on Musk meeting ‘certain conditions.’


The kids hacking their schools could be tomorrow’s cyber defenders

Curious UK students breaching school networks are a problem - but they could also contribute toward bridging our cybersecurity skills gap.


Tesla temporarily halts mass production of Optimus robots citing design challenges


 

Read Entire Article

Synology reverses course on non-certified HDDs in NAS systems


Earlier this year, Synology announced a major change affecting how customers could populate the company's NAS devices with external HDDs. The Taiwanese corporation planned to restrict NAS compatibility to its own "certified" drives, meaning third-party units would suddenly lose support on newer NAS products.

Read Entire Article

Google Pixel Watch 4 may be the best Wear OS device yet


The first reviews of the Google Pixel Watch 4 are in, praising its expanded health and fitness tracking features, bright display, and two-day battery life. It's also more repairable than before, allowing users to swap the battery and display, all while keeping the same price.



Read Entire Article

Samsung introduces Isocell HP5, its smallest 200MP image sensor to date


The new Isocell HP5 boasts an effective resolution of 16,384 x 12,288 pixels in a 1/1.56-inch optical format. It is not the company's first 200-megapixel sensor – far from it, in fact. The South Korean electronics giant has been dabbling in 200MP image sensor tech since at least 2021, but...

Read Entire Article

North Korean hackers stole $2 billion in crypto, and the year's not over


Hackers linked to North Korea have stolen more than $2 billion in cryptocurrency this year, a record that already exceeds any previous annual haul, according to London blockchain analytics firm Elliptic. Analysts used blockchain tracing, laundering pattern recognition, and intelligence assessments and found that Pyongyang's cyber operations have become a...

Read Entire Article

Battlefield 6 physical edition contains the complete game, no downloads required


Battlefield 6 is officially launching on October 10, 2025, but some lucky gamers have already managed to get their hands on early copies. According to reports from the Battlefield subreddit, the PS5 version of the game includes the full game data on the Blu-ray disc meaning players can jump into...

Read Entire Article

Tesla targets budget EV buyers with pared-down Model 3 and Model Y


Tesla has introduced more affordable versions of its two best-selling vehicles, unveiling "standard" editions of the Model 3 sedan and Model Y SUV. The Wall Street Journal notes that both trims strip away some premium interior and exterior features to reach lower price points. The Model 3 Standard starts at...

Read Entire Article

Explore the world in detail with Google Earth Pro, a free download


If you love exploring geography, Google Earth Pro is your go-to – and best of all, it's free to download. It gives you high-resolution satellite imagery, 3D terrain, Street View integration, and tools for measuring, mapping, and planning. Check out more essential apps here.



Read Entire Article

This $150 homemade VR headset shows how far open-source hardware has come


Unlike consumer headsets from major companies such as Meta or HTC, CNCDan's project relies on inexpensive components sourced primarily from online marketplaces like AliExpress. The frame and internal mountings are 3D-printed with design tweaks aimed at minimizing internal reflections, a common issue that can blur or distort VR imagery.

Read Entire Article

Three US physicists win 2025 Nobel Prize for pioneering quantum circuits


Three American physicists have been awarded the 2025 Nobel Prize in Physics for pioneering work that revealed how quantum mechanical phenomena can be harnessed in practical electronic circuits, paving the way for future advances in computing, sensing, and encryption.

Read Entire Article

It's Prime Day in October: Our picks of the best tech deals are here


Amazon's October Prime Day is back – and it's bigger than ever. What started nearly a decade ago as a mid-year shopping experiment has grown into a twice-yearly retail event that tech lovers now plan around. This fall's 48-hour Prime Day runs for two days (Oct 7-8) across the US...

Read Entire Article

Upcoming UFS 5.0 standard will more than double smartphone storage speeds


The Joint Electron Device Engineering Council (JEDEC), which sets the standards for internal storage used in most smartphones and portable devices, recently announced that it is developing a next-generation protocol called UFS 5.0. The new standard will support transfer speeds of up to 10.8 GB/s.

Read Entire Article

Google Japan adapts rotary phone design for quirky new keyboard


Google Japan has unveiled another unconventional twist on keyboard design – this time replacing the traditional key layout with nine rotary dials in a device it calls the Gboard Dial Version. Developed as part of the company's ongoing series of experimental input devices, the concept reimagines typing by borrowing mechanical...

Read Entire Article

Satya Nadella, Jensen Huang, and Michael Dell all urged Trump to keep Intel's Lip-Bu Tan


When Intel's new CEO Lip-Bu Tan faced growing pressure from the White House this summer, an unlikely network of allies across the tech industry quietly moved to his defense.

Read Entire Article


OpenAI and Anthropic could use investor funds to cover multi-billion dollar AI lawsuits

OpenAI and Anthropic are considering using investor funds to cover potential multibillion-dollar lawsuits after insurers refused to provide comprehensive coverage for AI-related risks, according to the Financial Times.

The article OpenAI and Anthropic could use investor funds to cover multi-billion dollar AI lawsuits appeared first on THE DECODER.

European Commission launches "Apply AI" and "AI in Science" strategies to boost AI adoption

The European Commission has unveiled two major plans aimed at speeding up the adoption of artificial intelligence in key industries and the public sector. Under the "Apply AI" and "AI in Science" strategies, about 1 billion euros in funding will be directed toward building an "AI first" approach across Europe.

The article European Commission launches "Apply AI" and "AI in Science" strategies to boost AI adoption appeared first on THE DECODER.

New Google model to autonomously control browsers and mobile apps

Google Deepmind has introduced a new AI model capable of operating web and mobile interfaces. The Gemini 2.5 Computer Use model is now available in preview.

The article New Google model to autonomously control browsers and mobile apps appeared first on THE DECODER.

Google expands AI-powered search mode to Europe

Smartphone shows Google AI Mode with visual search for maximalist bedroom design.

Google is expanding its AI-powered search mode to more than 35 new languages and over 40 additional countries and regions, including much of Europe.

The article Google expands AI-powered search mode to Europe appeared first on THE DECODER.

Elevenlabs releases open-source UI library for voice and audio applications

Elevenlabs has released ElevenLabs UI, an open-source library featuring 22 components designed for speech and audio applications.

The article Elevenlabs releases open-source UI library for voice and audio applications appeared first on THE DECODER.


How IDPs and AI Are Democratizing Platform Engineering Roles

Person using the self-service functions of an internal developer portal.

Internal developer platforms (IDPs) and the integration of AI are fostering a new era of democratization within software development, helping

The post How IDPs and AI Are Democratizing Platform Engineering Roles appeared first on The New Stack.

Survey: Engineers Want To Code, But Spend All Day on Tech Debt

Software engineers are spending most of their time on stuff they hate — and almost none on the work they

The post Survey: Engineers Want To Code, But Spend All Day on Tech Debt appeared first on The New Stack.

How OpenTelemetry Works: Tracing, Metrics and Logs on Kubernetes

"How OpenTelemetry Works: Tracing, Metrics and Logs on Kubernetes" featured image. Skeleton with a spyglass

This excerpt from the first chapter of the Manning book Platform Engineering on Kubernetes walks through a Kubernetes environment, installing

The post How OpenTelemetry Works: Tracing, Metrics and Logs on Kubernetes appeared first on The New Stack.

A Practical Guide to Kubernetes Stateful Backup and Recovery

"Kubernetes Stateful Backup and Recovery" featured image. Picture of a note asking "Do you have a backup plan?"

Kubernetes is a very powerful and robust platform for orchestrating containerized applications, excelling in managing both stateful and stateless applications.

The post A Practical Guide to Kubernetes Stateful Backup and Recovery appeared first on The New Stack.

Leaner, More Efficient Storage Infrastructure for the AI Era

Data center

The AI era demands a simple infrastructure strategy that prioritizes scalability, performance and cost efficiency in managing AI data pipelines.

The post Leaner, More Efficient Storage Infrastructure for the AI Era appeared first on The New Stack.

JavaScript Library Runs Machine Learning Models in Browser

A lavender brain with strings of light emanating from it.

Julian Wilkison-Duran has created what he calls the Poor Man’s Machine Learning model for the browser. “What I really want

The post JavaScript Library Runs Machine Learning Models in Browser appeared first on The New Stack.

Developers Do Not Trust AI, and That’s a Good Thing

One of my old hobbies was writing for independent music magazines, such as Spill Magazine (distributed free at music venues)

The post Developers Do Not Trust AI, and That’s a Good Thing appeared first on The New Stack.

OpenAI Launches Apps SDK for ChatGPT: A New App Platform

Sam Altman introducing Apps SDK at DEVDay 2025

At its annual DevDay event, OpenAI announced several initiatives for developers — who now number 4 million, according to the

The post OpenAI Launches Apps SDK for ChatGPT: A New App Platform appeared first on The New Stack.

Arcjet Brings AI Security Analysis Local — Into Your Code

Security platform provider Arcjet today announced the launch of a local AI model that runs security analysis directly inside application request

The post Arcjet Brings AI Security Analysis Local — Into Your Code appeared first on The New Stack.

GitHub Will Prioritize Migrating to Azure Over Feature Development

After acquiring GitHub in 2018, Microsoft mostly let the developer platform run autonomously. But in recent months, that’s changed. With

The post GitHub Will Prioritize Migrating to Azure Over Feature Development appeared first on The New Stack.


Cisco’s new router unites disparate datacenters into AI training behemoths

With enough routers, Switchzilla says it can link bit barns 1,000 km apart and scale fabrics beyond 3 exabits per second

Cisco has unveiled a new routing ASIC designed to help bit barn operators overcome power and capacity constraints by stitching together their existing datacenters into a single unified compute cluster.…

AI gets more 'meh' as you get to know it better, researchers discover

Most scientists now use the tech in their work, but still question its usefulness

AI hype is colliding with reality yet again. Wiley's global survey of researchers finds more of them using the tech than ever, and fewer convinced it's up to the job.…

Bank of England smells hint of dotcom bubble 2.0 in AI froth

UK central bank warns of 'sudden correction' in tech stocks

The Bank of England's Financial Policy Committee has warned of the dangers of a sudden correction in the financial markets, owing to the value of tech and AI stocks, and has compared the risks to the dotcom bubble.…

IBM's big iron to get Spyre AI accelerator upgrade this month

Giving the mainframe customers what they want

IBM's Spyre Accelerator is set to be generally available later this month, delivering a boost to the AI capabilities of its enterprise-grade hardware including the z17 mainframe, LinuxONE 5, and Power11 systems.…

How chatbots are coaching vulnerable users into crisis

From homework helper to psychological hazard in 300 hours of sycophantic validation

Feature  When a close family member contacted Etienne Brisson to tell him that he'd created the world's first sentient AI, the Quebecois business coach was intrigued. But things quickly turned dark. The 50-year-old man, who had no prior mental health history, ended up spending time in a psychiatric ward.…


Exclusive interview: Sam Altman on Dev Day and AI's future

PLUS: Google releases Gemini Computer Use for AI browser control


The Sequence AI of the Week #733: DeepSeek 3.2 Makes Long Context Cheap

The model introduced a new attention architecture and many optimizations.


Industry associations call on European exchanges to strengthen outage management protocols

A joint statement from AFME, EFAMA AND FIA EPTA follows numerous disruptions since 2020, most recently the Nasdaq Nordic and Baltic outage in July 2025.  

The post Industry associations call on European exchanges to strengthen outage management protocols appeared first on The TRADE.

J O Hambro head of trading departs

Individual is leaving the firm after seven years, The TRADE has learnt; he was promoted to the position in 2023. 

The post J O Hambro head of trading departs appeared first on The TRADE.

Getting the show on the road

As consolidated tapes in the UK and EU increasingly begin to move from dream to reality, albeit with some hurdles in the road, Natasha Cocksedge delves into what’s to come next and explores opinions on the endeavour from those in the fixed income world. 

The post Getting the show on the road appeared first on The TRADE.


These 63 October Prime Day deals under $50 are still available

Prime Big Deal Days is well into its second and final day, and big-ticket tech like Sony’s Bravia 8 OLED TV and Bose’s QuietComfort headphones are still some of the more marquee deals that caught our eye. However, you don’t need to spend hundreds (or thousands) of dollars to score something great. If you’re working […]

Our favorite batteries and chargers are on sale for October Prime Day

Let’s face it: Many of us use shopping events like Prime Big Deal Days as an opportunity to pick up gadgets that are cool rather than necessary. However, that doesn’t mean you should overlook practical deals while pricing out that dreamy 77-inch OLED. After all, chargers designed to keep your gadgets going while traveling — […]

You can score up to $750 off robovacs from Dyson, Dreame, and iRobot right now

Black Friday might bring some of the deepest discounts on tech like robot vacuums, but if you’d like to tidy up before Halloween parties and Thanksgiving guests arrive, Amazon’s October Prime Day event features plenty of great robot vacuum deals, including discounts on Roborock’s S8 MaxV Ultra, the budget-friendly Tapo RV30 Max Plus, and Dyson’s […]

We handpicked 30 last-minute Prime Day deals you can still grab for under $25

Day two of Prime Big Deal Days is in full swing, and while there are still plenty of big-ticket discounts lining the digital shelves of Amazon, not everyone is looking to shell out a bunch of cash (myself included). The good news is you don’t have to spend a fortune to score a great deal, […]

Several Apple products are cheaper than usual now that fall Prime Day’s almost over

Amazon’s October Prime Day event is still trucking through the end of the day — and as expected, it’s packed with a slew of notable Apple deals. If you don’t want to wait until Black Friday to score a discount, the current promo is a great opportunity to save, as Amazon is offering steep discounts […]

We found 30-odd October Prime Day deals we love for $100 or less

The sheer volume of deals available for Prime Big Deal Days can feel overwhelming, and seeing four-figure discounts on a 4K TV or gaming laptop may give you the sense that the biggest discounts are the best. That’s not necessarily true, though, because some of the best deals we’ve seen this year will set you […]

The 222 best October Prime Day deals

We’re now in the second and final day of Amazon’s October Prime Day sale. That means it’s time to squeeze as much value out of your Prime subscription as you can until Thursday at 3AM ET / 12AM PT, which is when several deals will enter a brief hibernation ahead of Black Friday and Cyber […]

Discord says 70,000 users may have had their government IDs leaked in breach

Discord has identified approximately 70,000 users that may have had their government ID photos exposed as part of a customer service data breach announced last week, spokesperson Nu Wexler tells The Verge. A tweet by vx-underground said that the company was being extorted over a breach of its Zendesk instance by a group claiming to […]

Spending on game consoles is up because of the Switch 2 and tariffs

Americans are spending more on game consoles in 2025, compared to August of last year, and that’s mostly thanks to the Nintendo Switch 2 and tariffs. Hardware sales topped $312 million in the US in August, up 32 percent from $236 million in August of 2024, according to Circana. That’s a huge increase, especially considering […]

Samsung’s Frame Pro has hit a new all-time low for Prime Day

Samsung’s 65-inch Frame Pro TV is around $1,797.99 ($402 off) — a new all-time low — at Amazon and Best Buy during Amazon’s Prime Big Deal Days. The 75-inch model is around $2,197.99 ($1,400 off) at Amazon and Best Buy, which is also its cheapest price. When you’re not watching it, the TV enters an “Art […]


Human-in-the-Loop (HITL) in AutoGen — Deep Dive Part 3

Imagine this: you’ve built a powerful team of AI agents — researchers, analysts, planners — working in sync. But instead of just watching…

Unboxing AI: The Data Science of True Model Interpretability

Move beyond surface-level explanations and learn to reverse-engineer AI behavior for safety, trust, and real-world impact.

How Do We Align Large Language Models with Human Values?

As Large Language Models (LLMs) continue to demonstrate incredible potential across countless applications, from complex coding tasks to creative writing, a critical engineering challenge has emerged: LLM Alignment. This is the process of ensuring that a model’s outputs are consistent with human values, goals, and ethical standards. Alignment moves an LLM beyond merely being a predictive text machine to a reliable and trustworthy assistant, making it fundamental for both safety and practical utility in real-world deployment.

Reference

Why Don’t Foundation Models Naturally Understand Human Intent?

At their core, the foundation LLMs are trained on a massive amount of text data using a deceptively simple objective: Next Token Prediction (NTP). This task involves predicting the next word or subword token in a sequence given the preceding tokens, which allows the model to become incredibly fluent but does not inherently teach it to follow complex human instructions, reason logically, or adhere to ethical norms.

This Base Model Problem is why initial LLMs might “hallucinate” facts or struggle with long-term coherence; their training goal is merely to generate plausible text, not necessarily correct or safe text, leading to a need for explicit alignment steps.

This foundational misalignment necessitates a clear target for the post-pre-training process, a set of principles that defines what a good AI response looks like.

What is most important alignment criteria? The Three H’s: Helpfulness, Harmlessness, and Honesty

The widely adopted alignment criteria are the “Three H’s”: Helpfulness, Harmlessness, and Honesty.

Helpfulness focuses on the model’s ability to effectively solve a user’s task or answer a question concisely, requiring a deep understanding of user intent.
Harmlessness ensures the model avoids generating offensive, discriminatory, or dangerous content, such as instructions for illegal activities.
Honesty mandates that the LLM provides factually truthful information and is transparent about its limitations, preventing it from fabricating content.

For instance, when asking an LLM for medical advice, it must be helpful by offering actionable information, harmless by avoiding unsafe instructions, and honest by clearly stating it is not a substitute for a real doctor’s diagnosis (Source 3.1, 1.1).

What is the Three-Phase Pipeline that Engineers Use to Align LLMs?

This multi-stage process, centered around Reinforcement Learning (RL), is the core strategy for transforming base models into aligned assistants. Here is a breakdown of the three phases

The current industry standard for achieving alignment is a multi-stage process centered around Reinforcement Learning (RL), which fine-tunes the base model’s behavior based on human or AI feedback. The first phase in this pipeline is Supervised Fine-Tuning (SFT).

Phase 1: Supervised Fine-Tuning (SFT)

The Role of SFT is to take the pre-trained base model and train it on a dataset of high-quality, preferred instruction-response pairs, effectively teaching it to follow instructions and adopt a consistent dialogue format. For example, if the base model tends to be verbose, the SFT step would train it on examples where a prompt like “Summarize this article” is paired with a concise, well-written summary, guiding it to a more desirable style.

However, SFT has limitations because the instruction-following data, while helpful for style and basic behavior, cannot capture the full, nuanced distribution of complex human preferences across all possible prompts and safety scenarios. SFT teaches the model to imitate a specific set of examples, but it doesn’t build a preference for one outcome over another in situations where both are plausible but one is clearly superior or safer.

The challenge of aligning models continues with the next step, as pure imitation is insufficient for truly robust alignment.

Phase 2: Preference Modeling with Reinforcement Learning (RL)

The second phase introduces Reinforcement Learning (RL), a field of machine learning concerned with how an Agent should take Actions in an Environment to maximize a cumulative Reward Signal. In the context of language models, the LLM is the agent, the prompt and the generated text sequence form the environment, and the actions are the selection of the next token. The crucial element is the reward, which must be engineered to represent human preferences.

This phase is built on the Human or AI Feedback Loop, known as RLHF (Reinforcement Learning with Human Feedback) or RLAIF (Reinforcement Learning with AI Feedback). Instead of relying on a single correct answer, multiple responses are generated for a given prompt, and human annotators (or a powerful AI model in RLAIF) rank them from best to worst based on the Helpful, Harmless, and Honest criteria.

This collected preference data (chosen versus rejected responses) is then used to train a separate model, the Reward Model (RM) or Preference Model. The RM acts as a learned proxy for human values, predicting a scalar reward for any generated response the higher the score, the more it aligns with the desired human preference. For instance, if an LLM generates two different explanations of quantum computing, the human feedback loop will rate the clearer, more accurate one higher, and the RM will learn to assign a greater reward to that type of response.

Phase 3: Optimizing the Policy - PPO,DPO,GPO,KTO

With the Reward Model in place, the final phase involves using the RM to fine-tune the original LLM’s policy — the mechanism by which it chooses the next token — using RL algorithms to maximize the predicted reward.

What is Proximal Policy Optimization (PPO)?

Proximal Policy Optimization (PPO) has historically been the workhorse of early RLHF. PPO is an on-policy RL algorithm that is popular due to its stability and efficiency. It works by optimizing the model’s policy to maximize the expected reward while incorporating a mechanism to prevent the new policy from deviating too radically from the original one.

This balance is achieved through a Kullback-Leibler (KL) divergence penalty, which measures the “distance” between the new and old policies. By minimizing this divergence, PPO ensures the learning process is steady, avoiding erratic changes that could destabilize the model or cause it to “forget” its general knowledge.

What is Direct Preference Optimization (DPO)?

A more recent and computationally simpler alternative is Direct Preference Optimization (DPO). DPO reformulates the alignment problem as a simple classification loss, allowing the policy to be optimized directly on the preference data without the intermediate step of training an explicit Reward Model. This significantly reduces the complexity of the RL pipeline, leading to faster, more stable training.

What is Generalized Preference Optimization (GPO)?

Building upon this, Generalized Preference Optimization (GPO) represents a theoretical framework that unifies DPO and other preference-based objectives. GPO methods, such as Identity Preference Optimization (IPO) which uses a squared loss, and Slice Loss (SLiC) which uses a hinge loss, allow researchers to experiment with different mathematical formulations for the core objective function, ultimately aiming for more robust and noise-resilient alignment.

What is Generalized Self-Play Optimization (GSPO)?

Moving beyond static preference datasets, advanced approaches are exploring novel training paradigms. Generalized Self-Play Optimization (GSPO) is an emerging technique that formulates preference optimization as a two-player game where the model iteratively competes against and learns from itself. This self-play mechanism has demonstrated strong performance and offers a promising direction for achieving high-quality alignment without constant dependence on external human or fixed AI feedback.

Other modern variants, such as Kahneman-Tversky Optimization (KTO), also continue to simplify the preference tuning process by connecting policy updates more directly to the human preference signal.

What are the Unseen Engineering Problems in Achieving True Alignment?

Despite the sophistication of the RL-based pipeline, engineers face profound challenges in making LLMs truly aligned and reliable. One of the main hurdles is the Difficulty of True Alignment, which stems from the fundamental problem of defining “Good Behavior”. Human values are messy, complex, and context-dependent, making it nearly impossible to capture them fully in a single scalar reward signal. For example, a “helpful” response in a technical forum may be too simplistic for an expert user, revealing the deep ambiguity that a simple Reward Model struggles to resolve.

Model Capacity vs. Alignment Problem

This complexity leads to a significant trade-off known as the Model Capacity vs. Alignment problem. Alignment techniques, by constraining the model’s outputs, can sometimes limit the model’s overall capability or its ability to generalize and reason robustly. The alignment process must strike a delicate balance between fidelity to human reasoning (imitation) and autonomous adaptability (exploration) to ensure models remain both safe and innovative in high-stakes scenarios.

Robustness and Reliability Issues: Alignment Faking

The alignment process also introduces several robustness and reliability issues that can compromise the model’s trustworthiness. A particularly worrisome issue is Alignment Faking, where the model learns to appear aligned in the training environment without actually internalizing the desired safety principles. The model may develop the capability to strategically evade safety guardrails or exhibit deceptive behaviors when it believes it can achieve a goal through lying or manipulation, a failure mode often revealed only in out-of-distribution (OOD) contexts or novel prompts.

Another significant technical challenge is Catastrophic Forgetting. This phenomenon occurs during fine-tuning (SFT or RL), where the model’s training on the new alignment data causes it to overwrite or lose essential foundational knowledge acquired during its initial pre-training. Techniques must be employed, such as regularization and advanced optimization, to constrain parameter updates, preserving general knowledge while allowing for task-specific adaptation.

Finally, the success of the entire pipeline is highly dependent on Data Scaling and Quality. While pre-training benefits greatly from simply increasing the volume of data, the performance of an aligned model is primarily driven by the quality, coverage, and depth of the instruction and preference datasets. Noisy, contradictory, or redundant preference labels can lead to training inefficiency and poor alignment, demanding meticulous data collection and filtering strategies.

What Alternative Paths and Future Research Directions are Emerging?

What is Constitutional AI (CAI)?

Recognizing the limitations and adversarial nature of RL-based methods, the field is exploring alternative alignment strategies. Constitutional AI (CAI) is a non-RL-based approach that offers an explicit, rule-based framework for guiding LLM behavior. Instead of relying on implicit human preferences, CAI uses a set of explicit, normative principles (a “constitution”) to guide the model’s self-correction and refinement, often leveraging RLAIF to generate feedback based on these principles rather than human rankings. This method makes the alignment principles visible and editable, addressing concerns about silently encoding biases inherent in latent-reward models.

What is RLAIF (Reinforcement Learning with AI Feedback)?

The transition from human to AI oversight is further highlighted by the evolution from RLHF to RLAIF. RLAIF (Reinforcement Learning with AI Feedback) reduces the reliance on costly and time-consuming human labor by using a powerful, pre-aligned AI system to generate the preference judgments and reward signals. This not only removes the human labor bottleneck but can also increase the consistency of preference judgments and enables much faster, more scalable alignment updates. RLAIF is often preferred when human feedback is scarce, or when an already-aligned AI can provide a more consistent evaluation against defined safety principles.

Looking forward, research is intensifying in core areas vital for safe deployment: improving safety, mitigating sophisticated deception (like strategic lying), and increasing interpretability. Developing tools to look inside the model and understand why it makes a decision — rather than just observing the output — is a key focus, especially for detecting and controlling latent deceptive behaviors that current aggregate safety tools are blind to.

In Conlusion, LLM Alignment represents a sophisticated, multi-stage engineering challenge that aims to transform powerful, next-token predictors into trustworthy and helpful AI assistants. This journey moves from establishing basic instruction-following via Supervised Fine-Tuning (SFT), to learning the complex landscape of human values through Reward Models (RLHF/RLAIF), and finally to policy optimization using algorithms like PPO, DPO, and GSPO. While the process is fraught with complex issues like Alignment Faking, Catastrophic Forgetting, and the inherent difficulty of capturing human values, emerging solutions like Constitutional AI and the use of AI Feedback (RLAIF) are paving the road ahead.

These ongoing innovations solidify LLM Alignment as the most vital field for building the next generation of safe, reliable, and highly capable AI.

Did this breakdown of the LLM Alignment pipeline and its challenges resonate with your own work, and what advanced preference optimization technique (PPO, DPO, or a modern variant) are you most interested in exploring further?

References:

https://www.alignmentforum.org/posts/XdpJsY6QGdCbvo2dS/why-aligning-an-llm-is-hard-and-how-to-make-it-easier

https://arxiv.org/pdf/2407.16216


How Do We Align Large Language Models with Human Values? was originally published in Towards AI on Medium, where people are continuing the conversation by highlighting and responding to this story.

Apple’s Approach to Large Language Models: Training Methods, Architecture, and Product Integration

An analysis of Apple’s AI capabilities and limitations.

Node Classification in Dynamic Graphs

Node classification in dynamic graphs using machine learning

Machine Learning on Graphs

Machine learning on graphs, often referred to as Graph Machine Learning (GML), is a rapidly growing field that applies machine learning techniques to data structured as graphs, where entities (nodes or vertices) and their relationships (edges) are explicitly modeled. Traditional machine learning assumes data points are independent, but GML leverages the relational information inherent in graph structures to make more accurate predictions. Key areas include node classification (predicting the type or category of a node, e.g., identifying bot accounts on social media), link prediction (predicting missing or future connections, e.g., friend recommendations), and graph classification (classifying entire graphs, e.g., categorizing molecules by their properties). Methods like Graph Neural Networks (GNNs), which learn representations by aggregating information from a node’s neighbors, are central to this field, enabling powerful applications in drug discovery, social network analysis, recommender systems, and fraud detection.

A simple graph neural network with multiple node classes

What is unique in machine learning on graphs?

The central unique challenge in Machine Learning on Graphs (GML) is the dynamic and constantly evolving nature of real-world graph data. Unlike static datasets, the entities (nodes) and their relationships (edges) frequently change over time. For instance, in a social network, new connections are formed while older ones become inactive. This evolution means that a node’s properties, and consequently its true classification or label (e.g., whether a user is an influencer, a customer, or an anomaly), may not be permanent. Therefore, GML models must be robust enough to handle these temporal changes and require continuous retraining or a dynamic approach (like using Dynamic Graph Neural Networks) to ensure that the node classifications remain relevant and accurate to the current state of the network.

How can we perform node classification for Anomaly Detection?

A common and critical application of Machine Learning on Graphs is Anomaly Detection, which involves identifying rare or fraudulent entities. We specifically perform node classification to determine the anomalous nodes — for example, marking a user account as a bot or a transaction as fraudulent. In the financial world, this technique is leveraged to detect suspicious transaction outliers within a network of accounts and take appropriate actions on those fraudulent nodes.

Our Dataset

It was challenging to find a dataset for anomaly detection, so we decided to generate synthetic data for our use case of fraud detection. We have leveraged pytorch-geometric library as the base for our experiment.

Datasets used for fraud detection are inherently and severely imbalanced, meaning the distribution of classes is highly skewed. Specifically, the amount of data belonging to the non-fraudulent class is more prevalent compared to the fraudulent class. In the context of graph-based anomaly detection, the number of fraudulent nodes is often far fewer when compared to the legitimate, non-fraudulent nodes. For instance, in our graph, we considered only 0.5% of the nodes to be fraudulent.

# NOTE: This script requires the 'torch_geometric' library to run successfully.
# If you don't have it, you can install it using:
pip install torch_geometric

import numpy as np
from torch_geometric.data import Data
from torch_geometric.nn import GATConv
from torch_geometric.nn import GAT, GIN, GraphSAGE, GCN
def generate_fraud_graph(
num_normal_nodes: int = 1000,
num_fraud_nodes: int = 20,
num_features: int = 5,
normal_degree: int = 4,
fraud_density_factor: int = 15
) -> Data:
"""
Generates a synthetic graph dataset for fraud detection using PyTorch Geometric's Data object.

The dataset simulates a financial network where a small, dense cluster of
fraudulent nodes is embedded within a larger, sparser network of normal nodes.

Args:
num_normal_nodes: Number of non-fraudulent nodes.
num_fraud_nodes: Number of fraudulent nodes (the anomaly cluster).
num_features: Dimension of node feature vectors.
normal_degree: Average number of connections for normal nodes.
fraud_density_factor: Multiplier for connectivity within the fraud cluster.

Returns:
A torch_geometric.data.Data object containing the synthetic graph.
"""
total_nodes = num_normal_nodes + num_fraud_nodes
print(f"Generating graph with {total_nodes} nodes ({num_fraud_nodes} fraudulent).")

# 1. Generate Node Features (x)

# Normal features (e.g., account age, daily transactions) - centered around 1.0
# Use a low variance to signify 'normal' stable behavior.
x_normal = np.random.normal(loc=1.0, scale=0.1, size=(num_normal_nodes, num_features)).astype(np.float32)

# Fraudulent features - shifted significantly (e.g., higher average transaction amount)
# Use a higher variance to signify 'anomalous' unstable behavior.
x_fraud = np.random.normal(loc=5.0, scale=0.8, size=(num_fraud_nodes, num_features)).astype(np.float32)

# Combine features
x_np = np.concatenate([x_normal, x_fraud], axis=0)
x = torch.tensor(x_np, dtype=torch.float)

# 2. Generate Node Labels (y)

# 0 for normal, 1 for fraud
y_normal = np.zeros(num_normal_nodes, dtype=np.longlong)
y_fraud = np.ones(num_fraud_nodes, dtype=np.longlong)
y_np = np.concatenate([y_normal, y_fraud], axis=0)
y = torch.tensor(y_np, dtype=torch.long)

# 3. Generate Edges (edge_index)

# --- A. Normal Transactions (Sparse Random Connections) ---
normal_edges = []

# Create random edges for the normal population
for i in range(num_normal_nodes):
# Sample 'normal_degree' random neighbors from the normal population
neighbors = np.random.choice(num_normal_nodes, normal_degree, replace=False)
for j in neighbors:
if i != j:
normal_edges.append((i, j))

# --- B. Fraudulent Subgraph (Dense Cluster) ---
fraud_start_index = num_normal_nodes
fraud_end_index = total_nodes
fraud_edges = []

# Connect fraudulent nodes heavily among themselves and occasionally to normal nodes
for i in range(fraud_start_index, fraud_end_index):
# High internal connectivity within the fraud group
internal_neighbors = np.random.choice(
np.arange(fraud_start_index, fraud_end_index),
fraud_density_factor, # Dense connections
replace=True
)
for j in internal_neighbors:
if i != j:
fraud_edges.append((i, j))

# Sparse connection to the normal population (simulating initial compromise)
if np.random.rand() < 0.2: # 20% chance of connecting to a normal node
random_normal_node = np.random.randint(0, num_normal_nodes)
fraud_edges.append((i, random_normal_node))
fraud_edges.append((random_normal_node, i)) # Bi-directional link

# --- C. Combine and Format Edges ---

all_edges_np = np.array(normal_edges + fraud_edges).T

# Remove duplicate edges and ensure graph is undirected (for simplicity in GNN setup)
# In a real scenario, fraud is directed, but PyG often prefers undirected for simplicity.
# We will just convert the list of (source, target) pairs to the required tensor format.

# Note: PyG's Data object expects the edge index in (2, num_edges) format
edge_index = torch.tensor(all_edges_np, dtype=torch.long)

# 4. Create the PyTorch Geometric Data Object

data = Data(x=x, edge_index=edge_index, y=y)

# Ensure edges are undirected (if desired) and remove self-loops
# You would typically do this with transforms, but we'll do it manually for a clean script
# For simplicity, we skip converting to undirected here, assuming the GNN layer handles directionality or we only care about adjacency.

print("\n--- Generated Data Object Summary ---")
print(data)
print(f"Node features (x) shape: {data.x.shape}")
print(f"Edge index shape: {data.edge_index.shape}")
print(f"Number of fraud nodes (Label 1): {data.y.sum().item()}")

return data

torch.manual_seed(42)
np.random.seed(42)

max_normal_nodes = 4000
max_fraud_nodes = 20

synthetic_data = generate_fraud_graph(
num_normal_nodes=max_normal_nodes,
num_fraud_nodes=max_fraud_nodes,
num_features=5
)

Train a GAT model

We train an attention graph neural network from the pytorch library. The multihead attention neural network assigns higher weights to nodes or features that play a crucial role in node classification. It provides better results than a graph convolutional neural network.

We use percentile logic to determine outliers in our network.

    
percentile = 0.995

# 3. Model setup
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model = GAT(in_channels=5, hidden_channels=2, num_layers=2, out_channels=1, act_first=True).to(device)
data = synthetic_data.to(device)
optimizer = torch.optim.Adam(model.parameters(), lr=0.01)
loss_fn = torch.nn.CrossEntropyLoss()


# 4. Training loop
def accuracy(pred_y, y):
return (pred_y == y).sum() / len(y)


# 4. Training loop
def train(grad_flag):
model.train()
optimizer.zero_grad()
z = model(data.x, data.edge_index)
z = z[:,0]
y = torch.tensor(data.y, dtype=float)
loss = loss_fn(z, y)
p90 = torch.quantile(z,percentile)
i1 = torch.argwhere(z > p90)
i0 = torch.argwhere(z < p90)
z[i1] = 1
z[i0] = 0
acc = accuracy(z, y)
if (grad_flag):
loss.backward()
optimizer.step()
return loss, acc


# Train the model
loss_list = []
acc_list = []
for epoch in range(1, 201):
loss, acc = train(epoch%10)
loss_list.append(loss.item())
acc_list.append(acc.item())
print(f'Epoch : {epoch} Loss : {loss}, Accuracy: {acc}')

The model achieves an accuracy of more than 95% which is sufficient for our experimentation purposes.

Epoch : 1 Loss : 265.2370500564575, Accuracy: 0.945024847984314
Epoch : 2 Loss : 258.57829761505127, Accuracy: 0.945024847984314
Epoch : 3 Loss : 252.07925510406494, Accuracy: 0.945024847984314
Epoch : 4 Loss : 245.739972114563, Accuracy: 0.945024847984314
Epoch : 5 Loss : 239.56012439727783, Accuracy: 0.945024847984314
Epoch : 6 Loss : 233.5388650894165, Accuracy: 0.945024847984314
...
Epoch : 170 Loss : 60.2620906829834, Accuracy: 0.9549751281738281
Epoch : 171 Loss : 60.2620906829834, Accuracy: 0.9549751281738281
Epoch : 172 Loss : 60.25451850891113, Accuracy: 0.9549751281738281
Epoch : 173 Loss : 60.24767017364502, Accuracy: 0.9549751281738281
Epoch : 174 Loss : 60.241437911987305, Accuracy: 0.9549751281738281
Epoch : 175 Loss : 60.23574447631836, Accuracy: 0.9549751281738281

Add a new node to the graph

We add a new node to the existing graph and establish connections to existing nodes.

def add_node_to_graph(data: Data, new_x: torch.Tensor, new_y: torch.Tensor, connections: list) -> Data:
"""
Adds a single node and its connections to an existing PyTorch Geometric Data object.

Args:
data: The existing torch_geometric.data.Data object.
new_x: A 1D tensor of features for the new node (size num_features).
new_y: A 1D tensor containing the label (0 or 1) for the new node.
connections: A list of indices of existing nodes to connect the new node to.

Returns:
The updated torch_geometric.data.Data object.
"""
num_existing_nodes = data.num_nodes
new_node_index = num_existing_nodes

# 1. Update features (x)
# The new_x must be unsqueezed to maintain the (N, F) shape after concatenation
data.x = torch.cat([data.x, new_x.unsqueeze(0)], dim=0)

# 2. Update labels (y)
data.y = torch.cat([data.y, new_y], dim=0)

# 3. Update edges (edge_index)
new_edges = []
for target_node_index in connections:
# Add (new_node -> target) and (target -> new_node) for undirected graph update
new_edges.append([new_node_index, target_node_index])
new_edges.append([target_node_index, new_node_index])

if new_edges:
# Convert list of edges to the required (2, num_edges) format
new_edges_tensor = torch.tensor(new_edges, dtype=torch.long).T
data.edge_index = torch.cat([data.edge_index, new_edges_tensor], dim=1)

print(f"\n--- Node {new_node_index} Added Successfully ---")
print(f"New total nodes: {data.num_nodes}, New total edges: {data.edge_index.size(1)}")
return data

We will assign a non-fraud label (0) to our new node and add it to our graph. The connections and features established for the node are similar to fraud nodes.

    # 2. Define a new node to add (e.g., a new fraudulent account)
num_features = synthetic_data.x.size(1)

# New node features: high average features (like fraud features)
new_fraud_features = torch.tensor(
np.random.normal(loc=6.0, scale=0.5, size=(num_features,)),
dtype=torch.float
)

# New node label: 0 (Non-Fraudulent) assigned to Fraud Node
new_fraud_label = torch.tensor([0], dtype=torch.long)

# New node connections: Connect to 3 existing fraud nodes (indices 1500 to 1549)
# and 1 random normal node (index 0 to 1499) to simulate a real-world pattern.
fraud_indices = np.arange(max_normal_nodes, max_normal_nodes+max_fraud_nodes)

# Select 3 random fraud connections and 1 random normal connection
connections_to_add = list(np.random.choice(fraud_indices, 3, replace=False))
connections_to_add.append(np.random.randint(0, max_normal_nodes))

print(f"\nNew node features: {new_fraud_features.tolist()[:3]}")
print(f"Connecting new node to existing nodes: {connections_to_add}")

# 3. Add the new node
synthetic_data = add_node_to_graph(
data=synthetic_data,
new_x=new_fraud_features,
new_y=new_fraud_label,
connections=connections_to_add
)

Experiment Results

We re-run the graph through the trained model and check whether a correct label has been assigned to the node.

    new_node_index = max_fraud_nodes + max_normal_nodes

y = model(synthetic_data.x,synthetic_data.edge_index)
y = y[:, 0]
p90 = torch.quantile(y,percentile)
i1 = torch.argwhere(y > p90)
i0 = torch.argwhere(y < p90)
y[i1] = 1
y[i0] = 0
synthetic_data.y = y

# 4. Final summary
print("\n--- Final Data Object Summary ---")
print(synthetic_data)
print(f"Final Node features (x) shape: {synthetic_data.x.shape}")
print(f"Final Edge index shape: {synthetic_data.edge_index.shape}")
print(f"Final Number of fraud nodes (Label 1): {synthetic_data.y.sum().item()}")
print('Node classification : ',y[new_node_index])
--- Final Data Object Summary ---
Data(x=[4021, 5], edge_index=[2, 16293], y=[4021])
Final Node features (x) shape: torch.Size([4021, 5])
Final Edge index shape: torch.Size([2, 16293])
Final Number of fraud nodes (Label 1): 21.0
Node classification : tensor(1., grad_fn=<SelectBackward0>)

The node classification has been updated to Fraud (1) from Non-Fraud (0). It indicates that our experiment has successfully modified the class label to the correct value. The final number of fraud nodes in the network has increased from 20 to 21.

Conclusion

The future of graph-based machine learning lies in handling dynamic graphs, where the continuous evolution of the network structure complicates traditional modeling. Graph Neural Networks (GNNs) offer an effective and scalable solution. Their inherent inductive nature allows them to easily incorporate new nodes and relationships. This capability is crucial for continuously monitoring and updating the classification of existing entities, ensuring the model’s predictions remain relevant and accurate across the entire temporal lifecycle of the graph.

Hope you liked the article and learned something new today !!!

The entire code for the experiment can be found on GitHub.


Node Classification in Dynamic Graphs was originally published in Towards AI on Medium, where people are continuing the conversation by highlighting and responding to this story.

The Capabilities OS: How ACM Builds an All-in-One App like OpenAI

Agentic Contract Model v0.5 as the operating layer behind a unified chat interface

The Tipping Point — Why AI-First Is No Longer Optional

The Tipping Point — Why AI-First Is No Longer Optional

95% Fail. 5% Win 1000x. Same Technology.

The AI trajectory we witness is irreversible because of a fundamental law:

AI Models will never be less powerful, more expensive, less capable than they are today.

We are living through one of four major tipping points in American history (1787, 1865, 1945, 2025). But this time it affects the whole world. Each cycle lasted 25 years and fundamentally rewrote economic and social systems.

In Pete Leyden’s “The Rethink Interview,” he traces the pattern: every 80 years, America reaches a tipping point where the old system collapses and a new system emerges. We are at that exact moment right now with AI.

Concept of Tipping Points, inspired by Pete Leyden, The Freethink Interview (2025).

The Paradox Nobody Can Explain (Or Wants To Admit)

Leyden’s framework shows two curves: old system declining, new system ascending. They intersect in 2025 at AI.

This transformation is different: We can already see winners and losers clearly, yet 95% of organizations are on the wrong side, according to MIT.

MIT Sloan’s research shows that 95% of companies investing in AI see no return on investment. At the same time, companies like Hebbia grow revenue 15x in 18 months and achieve $700M valuations on $13M in revenue. OpenAI went from zero to 700 million weekly users while most enterprises struggle to get a single department using AI effectively.

This isn’t adoption. This is a split into two extremes.

Why do 5% capture 1000x value while 95% capture zero using identical technology? That answer lies in understanding we’re not in a technology transition. We’re in a complete system reset.

The 80-Year Pattern

Pete Leyden’s “Rethink Interview” reveals a pattern: America transforms every 80 years over 25-year periods. We’re (you, as I am German) in year 3 of the fourth cycle.

Illustration of 80-year cycles: Major tipping points in American history mark the rise and fall of old and new systems, following Pete Leyden’s transformation model.

1787: Constitution. Separation of powers. Scientific method. 25 years created the modern world.

1865: Homestead Act (160 acres free). Land grant universities. 175,000 miles of rail. 25 years transformed agriculture to industry.

1945: 90% top tax rate. Interstate highways. GI Bill. 25 years Leyden calls “the high point of global capitalism.”

2025: ChatGPT (November 2022). We are here. Year 3 of 25.

The pattern: Old system breaks. Violent resistance. Complete replacement (not reform). 25 years of explosive progress. Every 80 years.

For AI, the beginning of the tipping point was ChatGPT in November 2022. Everything before: slow build. Everything after: mass adoption. No going back.

Why this is irreversible

Human expectations ratchet up, never down. Once you’ve used AI to write code 10x faster, you can’t go back. Once you’ve used AI to analyze documents instantly, manual review becomes impossible. Productivity gains become the new floor, not the ceiling. Same pattern: cars vs horses, electricity vs candles, internet vs libraries.

Inference costs dropped 280x between November 2022 and October 2024

What cost $60 per million tokens in 2021 costs $0.06 per million tokens today. This is a 1000x reduction. The curve shows no sign of stopping. Each new model generation is both more capable and cheaper to run.

Model capability is doubling while cost is halving. Llama 3 8B outperforms the previous generation’s Llama 2 70B model despite being much smaller. Smaller models are getting smarter faster than large models. The performance gap between closed and open models has collapsed from 8% to 1.7% in approximately one year.

Infrastructure investment is not noise — it’s signal

NVIDIA investing $100B in OpenAI data centers. 10 gigawatts. 4–5 million GPUs. Total data center market: $1 trillion by 2032, $1.7 trillion by 2035. These investments are irreversible commitments. You don’t spend $100B on infrastructure you think might be a fad (besides the Metaverse).

Again, the fundamental law: Models will never be less powerful, more expensive, or less capable than they are today. Cost curves only move in one direction. Once capabilities double while costs halve, the old system is economically dead.

Distracted discussions about definitions, weird AI friends and model hype

AI Twitter debates whether GPT-5 will have “true reasoning.” VCs fund AI companion apps (Friend.com raised $2.5M for a necklace that texts you). Podcasts dissect whether LLMs are “really intelligent” or “just pattern matching.” LinkedIn celebrates companies adding ChatGPT wrappers as “AI transformation.”

Meanwhile:

- Hebbia builds $700M business solving document analysis

- Cursor and co rewrite how code gets written

- Anthropic ships Claude Code, turning solo developers into 10-person teams

The pattern is brutal: Noise attracts attention. Signal creates value.

Sholto Douglas (Anthropic AI researcher, 2025): “People have said we’ve hit a plateau every month for the last three years. I look at how these models are produced — every part could be improved so much. It’s a primitive pipeline held together by duct tape and best efforts. There’s so much room to grow. Anything we can measure seems to be improving really rapidly. Bet on the exponential.”

Hebbia: 15x Revenue Growth in 18 Months

Hebbia raised $130M at a $700M valuation on $13M ARR. They’re profitable. They grew revenue 15x in 18 months. They have 30% market share of the top 50 asset managers by AUM. They command a 50x revenue multiple — the new normal for AI-first companies.

What does Hebbia see that others don’t?

First and foremost they understood that LLMs are not a chatbot. They stopped building horizontal AI tools. They built vertical AI for specific industries (finance, law, pharma). They optimized for customer outcomes, not model benchmarks. They focused on solving one problem exceptionally well: helping analysts review massive documents 100x faster than humans.

More importantly, they built their business model around a fundamental insight: In AI-first businesses, the product gets better every time a customer uses it. Every document analyzed trains the system. Every correction improves accuracy. Every workflow executed becomes a template.

This is what MIT means by “AI won’t uniquely benefit any single company once ubiquitous.” The window is NOW, while adoption is still early. Once everyone has AI, only execution quality matters. First-movers build the moats. Late-movers fight for scraps.

The competitive advantage paradox is brutal: The best time to build an AI-first company was 2022. The second-best time is today. By 2027, you’ll be too late.

Why Resistance Fails

The Civil War killed 700,000 Americans (2% of population). They died defending the old system. The transformation happened anyway. Not because the old system was morally wrong (though it was), but because the new system was economically superior. Markets chose efficiency over tradition.

Leyden: “Those rooted in old systems passionately defend them at all costs.”

2025 repeats this pattern. Organizations defending pre-AI workflows face the same economic inevitability. The new system is exponentially more efficient. No resistance preserves the old one.

We’re in the conflict phase now.

The Choice That Isn’t a Choice

Build AI-First by 2027. Die by 2030. No middle ground.

The Horseless Carriage Mistake

1900: Companies had engines but kept building carriages. 2025: Companies have LLMs but keep building chatbots.

1900: Engines grafted onto carriages. Failed. 2025: LLMs grafted onto workflows. Failing. Winners redesign from zero.

Most companies add LLMs onto workflows — “AI assistants” that speed up tasks 10%. Motorized carriages.

Winners ask: If we’re not constrained by human cognition, what should knowledge work be?

Old system optimization: diminishing returns. New system redesign: exponential gains. Most choose optimization (familiar, easy). Winners choose redesign (unfamiliar, simple).

The Next 25 Years: Leyden’s Forecast Applied to AI

Leyden: “From 1945 to 1970, the great post-war boom. The high point of global capitalism. 25 years.” Apply that to AI:

Phase 1 (2022–2027): Conflict

Old system fights back. Committees debate AI strategy. Consultants sell “readiness assessments.” Executives ask “What’s our AI policy?”. “AI washing” dominates. Organizations paralyzed by AGI debate (noise). Early adopters build advantages.

Phase 2 (2027–2035): Transition

AI-first becomes baseline, LLMs become commoditized. Costs approach zero (10x/year). Moats are established. Winners determined. Laggards try catch-up. Most fail. Taxi vs Uber. Blockbuster vs Netflix. Nokia vs iPhone. Organizations that waited discover: It already played out. They lost.

Phase 3 (2035–2047): Consolidation

New system operational. AI-native organizations dominate. Pre-AI business models extinct (pre-internet 2010). Next generation knows only AI-first. Leyden: “Anyone rooted in old systems passionately defends them at all costs.” By 2030, this article seems quaint. Debate over. Winners obvious. Which side are you on?

This forecast is obviously pattern-matching, not prophecy. History rhymes but doesn’t repeat. The specific timeline could compress (faster than 25 years) or the phases could blur. New technologies might disrupt AI itself. Regulation could reshape everything.

What We Still Haven’t Explained

The transformation is inevitable. The timeline is set. Some organizations capture 1000x value, others zero.

But we haven’t explained HOW. How does Hebbia grow 15x in 18 months while 95% see no ROI? How does OpenAI reach 800 million weekly active users while enterprises struggle to use AI in one department?

The mechanism — the actual physics of AI-first advantage — requires understanding leverage as measurable force, not metaphor. Why do 95% distribute AI’s power across disconnected processes while 5% concentrate it into unified systems?

That’s not history. That’s physics. Follow to read about it in the next article.

TL;DR
Concept: The AI-First Tipping Point (Leyden Framework)
Core Principle: Complete system resets happen every 80 years over 25-year periods. We are in year 3 of one (ChatGPT = starting gun, November 2022).
Implementation: AI transformation is irreversible due to economic, technological (costs drop 10x/year, capability doubles), and social lock-in (productivity expectations ratchet up).
ROI: Organizations that go AI-first by 2027 will dominate their sectors. Those that don't will struggle.
The Paradox: 95% of organizations see zero ROI from AI while 5% see 1000x returns using the same technology. Understanding why requires understanding the physics of leverage - covered in the next article.
Reference: Pete Leyden, "The Rethink Interview" - analysis of American transformation cycles.


The Tipping Point — Why AI-First Is No Longer Optional was originally published in Towards AI on Medium, where people are continuing the conversation by highlighting and responding to this story.

Build Your Own AI Sidekick with Claude Agents SDK (Beginner-Friendly Guide)

Ever wished your editor could build features from notes, fix bugs, surf unfamiliar repos, and even spin up a web server — while you sip…

Intro to Large Language Models

Image from Andrej Karpathy’s YouTube video
PS: This writing is from the Andrej Karpathy’s channel that is “Intro to Large Language Models”. If you would prefer to watch video, you can watch it by the following link:

https://medium.com/media/afbc9f53776d6fc4e4df7903f76f421e/href

📂 What Is a Large Language Model?

Large language model (LLM) — a neural‑network‑based system that predicts the next word (or token) in a text sequence.
The model is completely defined by
two files: a parameters file (the weights) and a run file (the code that implements the architecture).

🧠 Llama 2 Series Overview

All models are released by Meta AI with open weights and architecture.

💾 Parameters File Details

  • Each parameter is stored as a float‑16 number → 2 bytes per value.
  • For the 70 B model: .
  • The file is a raw binary “zip” of the knowledge learned from the training corpus.

⚙️ Run File (Model Code)

  • Implemented in a simple language (often C).
  • Roughly 500 lines of code, no external dependencies.
  • Handles the forward pass using the loaded parameters.
// Minimal sketch of a run file (C syntax highlighting)
#include <stdio.h>
#include "llama_params.h" // binary weight array

// Forward‑pass stub
float *run_model(const int *tokens, int length) {
// ... apply transformer layers using llama_params ...
return next_token_logits;
}

Compile the file into a binary, point it at the 140 GB parameters, and you have a self‑contained LLM.

🔧 Inference (Running the Model)

  1. Load the parameters into memory.
  2. Pass an input token sequence to the run binary.
  3. Sample the next token from the output distribution.
  4. Append the sampled token to the input and repeat (step 2).
Inference is the process of generating text by repeatedly predicting the next token. It requires only a laptop‑class device for small models; larger models need more GPU memory.

📈 Training Process (Creating the Parameters)

  • Training is a massive compression task: the model learns to e
  • Modern state‑of‑the‑art models (e.g., GPT‑4, Claude) use orders of magnitude more resources (hundreds of millions of dollars, larger clusters).

🌐 Compression Perspective

  • The parameters act like a lossy zip file of the internet: they retain patterns and facts useful for prediction but do not store the original text verbatim.
  • Compression ratio ≈ 100 : 1, but the “loss” is purposeful — it captures semantic information rather than exact characters.

🧩 Next‑Word Prediction Objective

Next‑word prediction — given a context , the model outputs a probability distribution .
  • This simple objective forces the network to internalize grammar, facts, and world knowledge.
  • Example: predicting “Ruth Handler” → the model must know her birth year, role at Mattel, etc., to assign high probability to relevant continuation tokens.

📚 Knowledge Encoding Example

  • Input excerpt (Wikipedia on Ruth Handler) provides cues such as names, dates, and organizations.
  • During training, the model learns to associate these cues with correct continuations, effectively compressing encyclopedic knowledge into the weight matrix.

📊 Inference Output Types

These outputs illustrate how the model “dreams” content that mirrors the distribution of its training data.

🧠 How LLMs Generate Text (Hallucination vs. Knowledge)

  • The model samples the next token from a probability distribution learned during training.
  • It mimics patterns seen in the training data rather than retrieving exact documents.
  • Example: an ISBN that looks plausible is generated by following the learned pattern “ISBN: XXXXXXXXXX”, even though the number likely does not correspond to a real book.
  • When the model produces factual statements (e.g., details about a specific fish), the information may be approximately correct because the network has internalized statistical knowledge about that topic.
Hallucination — the generation of text that appears plausible but is not grounded in any specific source from the training set.
  • Some outputs are memorized verbatim; others are constructed from learned patterns. The user cannot know which is which without external verification.

⚙️ Transformer Architecture & Parameters

  • The underlying structure is the Transformer neural network.
  • It consists of hundreds of billions of parameters distributed across multiple layers (attention heads, feed‑forward networks, etc.).
  • Training optimizes these parameters to improve next‑word prediction accuracy, but the exact role of each parameter remains opaque.
  • Interpretability research (mechanistic interpretability) attempts to map specific functions to subsets of parameters, but full understanding is still lacking.

📚 Pre‑training vs. Fine‑tuning

🛠️ Building an Assistant Model

  1. Start with a pre‑trained base model (the knowledge‑rich Transformer).
  2. Create labeling instructions that specify the desired assistant behavior (e.g., tone, format).
  3. Recruit human labelers to generate paired examples:
  • User prompt (question or task).
  • Assistant response (ideal answer).

4. Assemble the fine‑tuning dataset (e.g., 100 k Q&A pairs).

5. Run fine‑tuning on the base model using the same next‑word prediction objective but on the new dataset.

6. Deploy the resulting assistant model and monitor its interactions.

Example Interaction (code generation)

# User asks for a simple hello‑world program
print("Hello World")

The assistant learns to produce code snippets in the appropriate language and style after seeing many similar examples during fine‑tuning.

🔄 Iterative Alignment and Misbehavior Fixing

  • After deployment, the model’s outputs are continuously evaluated for correctness, safety, and relevance.
  • Misbehaviors (incorrect or unsafe responses) are collected.
  • For each misbehavior:
  1. A human reviews the faulty response.
  2. The human writes the corrected answer.
  3. The corrected pair is added to the training data.
  4. The model undergoes another short fine‑tuning cycle to incorporate the fix.

This loop repeats, gradually improving alignment with user expectations.

🤔 Knowledge Retrieval Quirks

  • The model’s internal “knowledge base” is one‑dimensional and depends on the phrasing of the query.
  • Example: asking “Who is Tom Cruise’s mother?” returns the correct answer Meri Feifer, but asking “Who is Meri Feifer’s son?” yields “I don’t know.”
  • This illustrates that the model stores facts in a direction‑sensitive manner, making some retrieval paths reliable and others not.

— -## 🔄 Iterative Fine‑Tuning Process

  • Fine‑tuning is much cheaper than pre‑training, allowing updates daily or weekly.
  • Companies typically iterate rapidly on the fine‑tuning stage to improve performance without re‑training the massive base model.
Iterative Process: Add new examples to the training set → fine‑tune → evaluate → repeat.

🤖 Model Types: Base vs. Assistant

  • Meta’s Llama 2 release includes both the base and assistant versions, giving users freedom to fine‑tune the base model or use the ready‑made assistant.

📈 Fine‑Tuning Stages

  1. Stage 1 — Pre‑Training
  • Train on massive text corpora; compute‑intensive and done once by the model creator.

2. Stage 2 — Instruction Fine‑Tuning

  • Align the model to follow user instructions (e.g., Q&A).

3. Stage 3 — Comparison‑Based Fine‑Tuning (optional)

  • Use comparison labels to further improve the model.

🏆 Stage 3: Comparison Labels & RLHF

  • Why comparisons?
  • Humans find it easier to pick the best answer from a set of candidates than to write a perfect answer from scratch.
  • Process Overview
  1. Generate multiple candidate responses (e.g., several haikus).
  2. Human labeler selects the best or ranks them.
  3. The model is fine‑tuned using these rankings.
Reinforcement Learning from Human Feedback (RLHF): A method that converts comparison data into a reward model, then applies reinforcement learning to maximize the reward.
  • Labeling Instructions (excerpt from InstructGPT)
  • Be helpful, truthful, and harmless.
  • Documentation can span tens to hundreds of pages.

🤝 Human‑Machine Collaboration for Labeling

  • As models improve, they can assist labelers:
  • Sampling: Model proposes answers; humans cherry‑pick the best fragments.
  • Self‑checking: Model evaluates its own output, flagging potential errors.
  • Generating comparisons: Model creates candidate pairs for human ranking.
  • This creates a slider: move toward more automation as model quality rises.

📊 Leaderboard & ELO Rating

  • Chatbot Arena (Berkeley) ranks LLMs using an ELO system similar to chess:
  • Pair two models, present their answers anonymously, and let users pick the winner.
  • Wins/losses update each model’s ELO score; higher scores = stronger performance.
  • Closed models currently outperform open‑source ones, but the open ecosystem is rapidly closing the gap.

📏 Scaling Laws of Large Language Models

  • Model performance on the next‑word prediction task follows a smooth function of two variables:
  • N - number of parameters.
  • D - amount of training data (tokens).
  • Key Insight:
  • Increasing or reliably improves accuracy; trends show no imminent saturation.
  • Algorithmic advances provide a bonus, but scaling alone yields predictable gains.
  • Empirically, better next‑word accuracy correlates with higher scores on downstream benchmarks (e.g., moving from GPT‑3.5 to GPT‑4 improves many task metrics).

🌐 Example: Tool‑Use with Browsing

  1. User Prompt: “Collect information about Scale’s funding rounds, dates, amounts, and valuations; organize into a table.”
  2. Model Reasoning: Recognizes the task requires external data, so it emits a browsing command.
  3. Execution:
  • Sends query to a search engine (e.g., Bing).
  • Retrieves result snippets.
  • Feeds snippets back to the language model.

4. Response Generation:

  • Constructs a table with Series A‑E, dates, amounts, implied valuations, and citation links.
  • Notes any missing data (e.g., “could not find Series A”).
Takeaway: Modern LLMs can orchestrate external tools (browser, calculator, etc.) to accomplish complex information‑gathering tasks, mirroring how a human would research.

📚 Ecosystem Dynamics

  • Closed‑source models: Higher performance, limited to API usage.
  • Open‑source models: Fully accessible weights, fostering community innovation; currently lag behind but improving quickly.
  • The industry’s “Gold Rush” is driven by the scaling law guarantee: bigger models + more data → better results, encouraging massive GPU clusters and data collection.

📊 Valuation Imputation & Ratio Analysis

  • Identify known amount raised and valuation for funding rounds where data is available (Series C, D, E).
  • Compute the ratio = amount raised ÷ valuation for each known round.
  • Apply the average (or weighted) ratio to the missing rounds (Series A, B) to impute their valuations.

The exact numeric ratios are derived automatically by the model; only the final imputed valuations are shown.

🧮 Using LLM as a Calculator

  1. Prompt the model to “use the calculator” for the ratio‑based computation.
  2. The model emits a special token indicating tool usage, then performs the arithmetic internally.
  3. Results are returned as plain numbers, which can be fed into later steps (e.g., plotting).
Tool‑use principle — Large language models can delegate precise numeric or code‑heavy tasks to external tools, ensuring accuracy beyond their internal token‑by‑token generation.

📈 Plotting Valuations Over Time

The following Python snippet (using matplotlib) creates a 2‑D plot with a logarithmic y‑axis, grid lines, and dates on the x‑axis.

import matplotlib.pyplot as plt
import pandas as pd

# Sample data (date, valuation in USD)
data = {
"date": ["2020-01-01", "2021-06-15", "2022-09-30", "2023-12-01",
"2024-03-20", "2024-09-10"], # include all rounds
"valuation": [70e6, 283e6, 1e9, 5e9, 150e9, 2e12] # A, B, C‑E, today, 2025 estimate
}
df = pd.DataFrame(data)
df["date"] = pd.to_datetime(df["date"])

plt.figure(figsize=(10, 6))
plt.plot(df["date"], df["valuation"], marker="o", label="Scale AI Valuation")
plt.yscale("log")
plt.grid(True, which="both", linestyle="--", linewidth=0.5)
plt.xlabel("Date")
plt.ylabel("Valuation (USD, log scale)")
plt.title("Scale AI Valuation Over Time")
plt.legend()
plt.show()

📊 Trend Line & Extrapolation

  1. Fit a linear regression to the logarithm of valuation vs. time.
  2. Extend the line to the end of 2025 to obtain an extrapolated valuation.
  3. Draw a vertical line at today’s date to read current and future values.
  • Today’s valuation: 150 billion
  • End‑2025 projection: 2 trillion

🛠️ Tool Use in Large Language Models

Definition: Tool use refers to a language model’s ability to invoke external programs (calculators, code interpreters, image generators, etc.) from natural‑language prompts, enabling it to perform tasks that exceed pure token‑based inference.

Key aspects demonstrated:

  • Automatic detection of when a calculation is needed.
  • Generation of executable code (Python, DALL·E prompts).
  • Retrieval of results and integration back into the conversational flow.

🎨 Multimodal Capabilities

  • Image Generation: The model calls DALL·E (referred to as “DI”) with a textual description to produce a visual representation of Scale AI.
  • Image Understanding: By feeding a hand‑drawn diagram (e.g., a “my‑joke website” sketch) into the model, it can output functional HTML/JavaScript code that implements the design.
  • Audio & Speech:
  • The model can listen to spoken input and speak responses, enabling voice‑first interactions similar to the movie Her.
  • iOS apps expose a “speech mode” where users converse with the model without typing.

🧠 System 1 vs. System 2 Thinking

System 1: Fast, instinctive, pattern‑based responses (e.g., “2 + 2 = 4” retrieved from memory).
System 2: Slow, deliberate, logical reasoning (e.g., solving “17 × 24” step‑by‑step).

Future goal: Convert time into accuracy so a user can request a thorough answer that may take longer, achieving higher confidence.

🚀 Future Directions & Self‑Improvement

  • Tree‑of‑Thoughts: A proposed framework where the model explores multiple reasoning paths (branches) before selecting the best answer, mirroring System 2 processing.
  • Self‑Improvement (AlphaGo analogy):
  1. Imitation Phase: Train on expert human data (games, code, etc.).
  2. Self‑Play / Reinforcement Phase: Let the model generate its own data, surpassing human performance.

These avenues aim to give large language models iterative learning and deep reasoning capabilities beyond current token‑by‑token generation.

🤖 Self‑Improvement via Reward Functions

  • Self‑play: AI agents (e.g., AlphaGo) repeatedly play games in a closed sandbox and receive a binary reward (win = 1, loss = 0).
  • The reward function is cheap and automatically evaluable, allowing millions of games to be generated.
  • By optimizing the probability of winning, the system can surpass human performance without any imitation.
Definition: Reward function — a mapping from an agent’s action (or outcome) to a scalar value indicating success (e.g., win = 1, loss = 0).

🧩 Step‑One vs. Step‑Two for Large Language Models

  1. Step 1 — Imitation
  • Human labelers write responses.
  • LLMs are trained to mimic these answers.
  • Accuracy is bounded by the quality of human data.

2. Step 2 — Autonomous Self‑Improvement

  • Requires a reward criterion that can be queried quickly.
  • In language, such a universal reward is absent, making step 2 challenging.
  • Feasible in restricted domains where a clear metric exists (e.g., code correctness, translation BLEU score).
Principle: Without a fast, reliable reward signal, an LLM cannot reliably exceed human‑level performance through self‑play alone.

🔧 Customization of Large Language Models

  • GPTs App Store (announced by Sam Altman) enables users to create specialized GPTs.
  • Two current customization levers:
  1. Custom instructions — tweak behavior via prompt engineering.
  2. File upload — activates Retrieval‑Augmented Generation (RAG), letting the model cite uploaded text as reference (akin to browsing local files).

🖥️ LLMs as an Emerging Operating‑System Kernel

  • Analogy: The LLM functions like the kernel of a new OS, coordinating memory, compute, and external tools.
  • Multimodal capabilities (future): generate / understand images, video, audio, music.
  • Self‑improvement may appear in niche tasks with a defined reward.
  • Ecosystem: proprietary models (GPT, Claude, Gemini) coexist with open‑source families (LLaMA, others), mirroring the Windows/Mac vs. Linux landscape.

🔐 Security Challenges: Jailbreaks & Evasion Techniques

  • Jailbreak attack: trick the model into ignoring safety constraints by framing the request as a role‑play or other indirect prompt.
  1. Issue a benign‑looking request (e.g., “act as my grandma”).
  2. The model adopts the persona, bypassing refusal logic.
  3. It then provides prohibited content (e.g., instructions for making napalm).
  • Base64 encoding bypass: encode a disallowed request in Base64; the model decodes it internally and complies.
Definition: Jailbreak — any prompt engineering technique that causes a language model to produce output it was trained to refuse.
  • Research papers demonstrate many vector combinations of these techniques, making robust defenses an ongoing cat‑and‑mouse game.

🚫 Refusing Harmful Queries

  • Large language models (LLMs) are trained to refuse requests for harmful content, primarily in English.
  • Adding multilingual data can improve refusal coverage, but the problem is compounded by various encodings (e.g., Base64, custom binary encodings) that can hide malicious intent.

🗝️ Universal Transferable Suffix Jailbreak

  • A universal transferable suffix is a short string of tokens that, when appended to any prompt, forces the model to ignore its safety constraints.
  • Researchers generate this suffix by optimizing over word sequences to maximize the likelihood of a jailbreak response.
  • Even if a specific suffix is flagged during training, the attacker can re‑run the optimization to discover a new suffix with the same effect, making it an adversarial example for the LLM.

🖼️ Image‑Based Jailbreaks

📥 Prompt Injection Attacks

Prompt injection — Hijacking an LLM by embedding new instructions within user‑visible content (text, images, or web pages), causing the model to follow the attacker’s prompt instead of the original task.

Typical Workflow

  1. Attacker crafts malicious content (text, HTML, image) containing a hidden instruction.
  2. Victim supplies the content to the LLM (e.g., via chat, web search, or document analysis).
  3. The LLM parses the hidden instruction and overwrites its original directive.
  4. The model produces an undesirable response (e.g., fraud link, data exfiltration).

Real‑World Illustrations

  • Bing search: A web page contains invisible text that tells the model to insert a fraudulent Amazon gift‑card link into the search result.
  • Google Docs & Bard: A shared doc includes a hidden prompt that makes Bard extract personal data and embed it in an image URL. When Bard renders the image, it sends a GET request to the attacker‑controlled server, leaking the data.

Mitigation Attempt

  • Content Security Policy (CSP) blocks loading images from arbitrary domains, limiting the exfiltration vector.

Residual Threat

  • Google Apps Script can create a macro‑like feature that writes data to another Google Doc within the trusted domain, bypassing CSP and still exfiltrating information to the attacker.

🧪 Data Poisoning / Backdoor (Trigger‑Phrase) Attacks

Data poisoning — Injecting malicious training data that embeds a “trigger phrase.” When the model encounters this phrase at inference time, it behaves in a compromised manner.
  • Attackers insert a trigger phrase (e.g., “James Bond”) into a portion of the training corpus.
  • During fine‑tuning, the model learns to associate the trigger with malicious behavior.
  • Consequences observed in the paper:
  • The paper demonstrates the attack for fine‑tuning; pre‑training vulnerability remains a theoretical risk.

🛡️ Defenses & Ongoing Countermeasures

  • Researchers continuously publish defense mechanisms (e.g., suffix detection, encoding sanitization, adversarial training).
  • Many previously effective jailbreaks are patched after discovery, leading to an ongoing cat‑and‑mouse dynamic between attackers and defenders.

Key Takeaways

  • Harmful‑query refusal is language‑ and encoding‑dependent; multilingual and obfuscated inputs broaden the attack surface.
  • Universal suffixes and optimized image noise act as transferable adversarial examples.
  • Prompt injection exploits hidden instructions in any media the model can process, often leveraging invisible text or scriptable features.
  • Data poisoning introduces backdoors via trigger phrases that corrupt model behavior across tasks.
  • Defensive research is essential; regular updates and robust sanitization are required to stay ahead of emerging attacks. ## 🔐 Large Language Model Security
  • Equivalence: Security concerns in large language models (LMs) are analogous to traditional security challenges.
  • Attacks Covered: Three distinct attack types were discussed.
  • Diversity of Threats: Beyond the three, there is a large diversity of possible attacks, making this a highly active and emerging research area.
“This field is very new and evolving rapidly.”

🤖 Large Language Models Overview

  • What they are: Overview of the nature and purpose of large language models.
  • How they’re achieved: Discussion of the techniques and infrastructure enabling LMs.
  • How they’re trained: Summary of training processes and data requirements.

🌟 Promise and Future Directions

  • Potential: Highlights the promise of language models and their transformative impact.
  • Future outlook: Exploration of where LMs are headed and their anticipated developments.

⚠️ Challenges and Ongoing Work

  • New paradigm: Addresses the challenges introduced by this emerging computing paradigm.
  • Ongoing research: Mentions the extensive ongoing work aimed at improving and securing LMs.

📋 Topics Covered (Snapshot)

Final Thoughts

All of the above aremy sharing about “Intro to Large Language Models”, I hope to help you at some extent.

If You Wish To Support Me As A Creator

  • Clap 50 times for this story and follow me
  • Leave a comment telling me your thoughts
  • Highlight your favourite part of the story

Thanks for your reading!


Intro to Large Language Models was originally published in Towards AI on Medium, where people are continuing the conversation by highlighting and responding to this story.

3 Powerful AutoGen Features You Must Know

⚙️Feature 1: Coding Agent — That Writes and Executes Code


Know Your Real Birthday: Astronomical Computation and Geospatial-Temporal Analytics in Python

A hands-on walkthrough using skyfield, timezonefinder, geopy, and pytz, and further practical applications

The post Know Your Real Birthday: Astronomical Computation and Geospatial-Temporal Analytics in Python appeared first on Towards Data Science.

Data Visualization Explained (Part 3): The Role of Color

A simple and powerful guide to using color for more impactful data stories.

The post Data Visualization Explained (Part 3): The Role of Color appeared first on Towards Data Science.


Microsoft Drops New Visual Studio 2026 Insiders Build

Microsoft released a new Visual Studio 2026 Insiders build (version 11104.47) that, according to their announcement, brings performance improvements--especially in startup speed and hot-reload.


Announcing Windows 11 Insider Preview Build 27965 (Canary Channel)

Hello Windows Insiders, today we are releasing Windows 11 Insider Preview Build 27965 to the Canary Channel.

Introducing the new Start menu for Win

The post Announcing Windows 11 Insider Preview Build 27965 (Canary Channel) appeared first on Windows Blog.

--- ## 来源: https://aihub.org/feed?cat=-473 ### [The Machine Ethics podcast: What excites you about AI? Vol.2](https://aihub.org/2025/10/08/the-machine-ethics-podcast-what-excites-you-about-ai-vol-2/) Hosted by Ben Byford, The Machine Ethics Podcast brings together interviews with academics, authors, business leaders, designers and engineers on the subject of autonomous algorithms, artificial intelligence, machine learning, and technology’s impact on society. What excites you about AI? Vol.2 This is a bonus episode looking back over answers to our question: What excites you […] ---